spark算子map reduce小案例

本文介绍了RDD的两种操作方式——转换和行动操作,详细讲解了map和reduce的用法,并提供了完整的mapAndReduce示例代码。通过实例展示了如何使用map和reduce计算平均值,鼓励读者实践和探索更多可能的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.RDD两种操作方式介绍

1.1 转换操作(Transformation)

转换操作(Transformation)使用了链式调用的设计模式,对一个RDD计算之后,转换为另一个RDD,然后这个RDD又可以经过转换,转换为另一个RDD。这个过程是分布式的,它 必须等待行动操作(Action)完成后,才真正的触发Spark提交作业,开始执行计算。

1.2行动操作(Action)

行动操作Action是和转换操作相对应的一种操作,在Spark程序运行中,每调用一次Action操作,都会触发一次Spark的作业提交,并 返回相应的结果

2.转换操作map()介绍

map函数定义如下:
def
map[U](f: (T) ⇒ U)(implicit arg0: ClassTag[U]): RDD[U]
 Permalink
Return a new RDD by applying a function to all elements of this RDD.
map方法将原来的RDD中类型为T的元素,通过用户自定义的函数f按照一对一地映射为U类型的元素。函数f可以是简单的加减,也可以是复杂的将一元组转换为二元组等等。
 val rdd1 = sc.parallelize(List(1,2,3,4))
 val maprdd1 = rdd1
头歌(EduCoder)平台上的Spark算子综合案例通常是为了帮助学生理解和掌握Apache Spark的核心概念及常用API的应用。以下是使用Java编写的一个较为复杂的Spark算子应用实例,它涵盖了多个重要算子的操作。 ### 场景描述: 假设我们有一个日志文件,每条记录包括用户ID、操作时间戳、事件类型等信息。我们的任务是从这个日志集中提取并处理数据,计算每个用户的活跃度得分,并找出最活跃的前N名用户。这里的“活跃度得分”可以简单地定义为某个时间段内用户触发不同类型事件次数的加权总和。 #### 步骤说明: 1. **准备环境** 首先配置好Java开发环境,并引入必要的依赖库(如通过Maven)。确保已经安装了Apache Spark并且能够正常运行。 2. **加载数据源** 使用`textFile()`方法读取HDFS或其他存储系统中的文本文件作为输入来源。如果是在本地测试,则可以直接指定路径指向本地文件系统的地址。 3. **解析原始日志** 日志格式可能是固定的,比如以逗号分隔符的形式存在。我们可以创建自定义函数来进行分割、映射转换,将字符串形式的日志转为易于后续处理的对象模型表示法(例如POJO类)。 4. **过滤无效或不符合条件的数据点** 应用filter()算子去除那些明显错误或者不符合业务规则的数据行。 5. **聚合统计** 根据用户标识进行group by 或者 reduceByKey 等聚集运算得出每位用户对应的各类活动计数。 6. **权重分配与评分计算** 定义一套合理的评价体系给定不同类型的事件设置相应的权重值,在这一步里对前面得到的结果进一步加工求得最终分数。 7. **排序选择Top N 用户** 利用sortByKey()/sortWith()配合take(n)选出排名靠前的一部分样本出来显示结果。 8. **保存输出至目标位置** 把经过以上流程获得的信息写出到另一个持久化介质上供之后查询展示之用。 9. **关闭资源释放连接** 最后记得结束Job作业清理现场保持良好习惯。 下面是具体的代码实现: ```java import java.util.Arrays; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.function.*; import scala.Tuple2; public class UserActivityAnalysis { public static void main(String[] args){ // 初始化Spark Context... JavaSparkContext sc = ... ; try { // 加载数据 JavaRDD<String> logLines = sc.textFile("hdfs://path/to/logs"); // 自定义LogEntry POJO 类代表单个日志项 JavaRDD<LogEntry> entries = logLines.map(new Function<String, LogEntry>() { @Override public LogEntry call(String line) throws Exception { String[] parts = line.split(","); return new LogEntry(parts[0], Long.parseLong(parts[1]), EventType.valueOf(parts[2])); } }); // 清洗数据 - 移除非有效项目 JavaRDD<LogEntry> validEntries = entries.filter(new Function<LogEntry, Boolean>() { @Override public boolean call(LogEntry entry) throws Exception { return entry.isValid(); // 假设有这样的校验逻辑 } }); // 聚合统计数据 -> Map<(userId,eventType)->count> JavaPairRDD<Tuple2<Long,EventType>, Integer> userEventCounts = validEntries.mapToPair(entry -> new Tuple2<>(new Tuple2<>(entry.getUserId(), entry.getEventType()), 1)) .reduceByKey((Integer a, Integer b) -> a + b); // 计算总体得分 JavaPairRDD<Long, Double> scoresByUser = userEventCounts.mapToPair(pair -> new Tuple2<>(pair._1()._1(), getWeightedScoreForEvent(pair._1()._2()) * pair._2()) ).reduceByKey(Double::sum); // 获取TOP-N List<Tuple2<Long,Double>> topUsers = scoresByUser.sortBy(x->x._2,false,1).take(10); System.out.println("Most active users:"); for (Tuple2<Long,Double> tuple : topUsers ) { System.out.printf("%d\t%.2f\n",tuple._1,tuple._2); } } finally { if(sc!=null && !sc.isClosed()){ sc.close(); } } } private static double getWeightedScoreForEvent(EventType eventType) { switch(eventType){ case LOGIN: return 1.0; // 登录动作权重较低 case PURCHASE: return 5.0; // 下单购买行为赋予权重较高 default: return 2.0; // 默认其他互动给予一般数值 } } } ``` 在这个例子中,我们结合了多种常见的Spark算子,如`map`, `flatMap`, `filter`, `reduceByKey`, `join`, `groupBy`, `sortByKey`等,来完成了从原始数据到有价值的商业洞察的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值