【SparkAPI JAVA版】JavaPairRDD——aggregateByKey(二)

2023-11-09 13:39

本文主要是介绍【SparkAPI JAVA版】JavaPairRDD——aggregateByKey(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JavaPairRDD的aggregateByKey方法讲解
官方文档说明
Aggregate the values of each key, using given combine functions and a neutral
"zero value". This function can return a different result type, U, than the type of
the values in this RDD, V. Thus, we need one operation for merging a V into 
a U and one operation for merging two U's. The former operation is used for
merging values within a partition, and the latter is used for merging values between
partitions. To avoid memory allocation, both of these functions are allowed to modify 
and return their first argument instead of creating a new U.Parameters:
zeroValue - (undocumented)
seqFunc - (undocumented)
combFunc - (undocumented)
Returns:
(undocumented)
中文含义

aggregateByKey函数对PairRDD中相同Key的值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey函数最终返回的类型还是Pair RDD,对应的结果是Key和聚合好的值;而aggregate函数直接是返回非RDD的结果,这点需要注意。在实现过程中,定义了三个aggregateByKey函数原型,但最终调用的aggregateByKey函数都一致。

方法原型
// Scala
def aggregateByKey[U: ClassTag](zeroValue: U, partitioner: Partitioner)(seqOp: (U, V) => U, combOp: (U, U) => U): RDD[(K, U)]
def aggregateByKey[U: ClassTag](zeroValue: U, numPartitions: Int)(seqOp: (U, V) => U, combOp: (U, U) => U): RDD[(K, U)]
def aggregateByKey[U: ClassTag](zeroValue: U)(seqOp: (U, V) => U, combOp: (U, U) => U): RDD[(K, U)]
// java
public <U> JavaPairRDD<K,U> aggregateByKey(U zeroValue,Partitioner partitioner,Function2<U,V,U> seqFunc,Function2<U,U,U> combFunc)
public <U> JavaPairRDD<K,U> aggregateByKey(U zeroValue,int numPartitions,Function2<U,V,U> seqFunc,Function2<U,U,U> combFunc)
public <U> JavaPairRDD<K,U> aggregateByKey(U zeroValue,Function2<U,V,U> seqFunc,Function2<U,U,U> combFunc)

第一个aggregateByKey函数我们可以自定义Partitioner。除了这个参数之外,其函数声明和aggregate很类似;其他的aggregateByKey函数实现最终都是调用这个。
第二个aggregateByKey函数可以设置分区的个数(numPartitions),最终用的是HashPartitioner。
最后一个aggregateByKey实现先会判断当前RDD是否定义了分区函数,如果定义了则用当前RDD的分区;如果当前RDD并未定义分区 ,则使用HashPartitioner。

实例
public class AggregateByKey {public static void main(String[] args) {System.setProperty("hadoop.home.dir","F:\\hadoop-2.7.1");SparkConf conf = new SparkConf().setMaster("local").setAppName("TestSpark");JavaSparkContext sc = new JavaSparkContext(conf);JavaPairRDD<String,Integer> javaPairRDD = sc.parallelizePairs(Lists.<Tuple2<String, Integer>>newArrayList(new Tuple2<String, Integer>("cat",3),new Tuple2<String, Integer>("dog",33),new Tuple2<String, Integer>("cat",16),new Tuple2<String, Integer>("tiger",66)),2);// 打印样例数据javaPairRDD.foreach(new VoidFunction<Tuple2<String, Integer>>() {public void call(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {System.out.println("样例数据>>>>>>>" + stringIntegerTuple2);}});JavaPairRDD<String,Integer> javaPairRDD1 = javaPairRDD.aggregateByKey(14, new Function2<Integer, Integer, Integer>() {public Integer call(Integer v1, Integer v2) throws Exception {System.out.println("seqOp>>>>>  参数One:"+v1+"--参数Two:"+v2);return Math.max(v1,v2);}}, new Function2<Integer, Integer, Integer>() {public Integer call(Integer v1, Integer v2) throws Exception {System.out.println("combOp>>>>>  参数One:"+v1+"--参数Two:"+v2);return v1+v2;}});// 打印结果数据javaPairRDD1.foreach(new VoidFunction<Tuple2<String, Integer>>() {public void call(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {System.out.println("结果数据>>>>>>>" + stringIntegerTuple2);}});}
}
结果
// 打印样例数据 这里的分区是两个 其中分区内都有一个相同key值
19/03/03 22:16:07 INFO Executor: Running task 0.0 in stage 0.0 (TID 0)
样例数据>>>>>>>(cat,3)
样例数据>>>>>>>(dog,33)
19/03/03 22:16:07 INFO Executor: Running task 1.0 in stage 0.0 (TID 1)
样例数据>>>>>>>(cat,16)
样例数据>>>>>>>(tiger,66)
19/03/03 22:16:07 INFO Executor: Running task 0.0 in stage 1.0 (TID 2)
// 第一个分区比较大小 14 3 => 14(cat) , 14  33 => 33(dog)
seqOp>>>>>  参数One:14--参数Two:3
seqOp>>>>>  参数One:14--参数Two:33
19/03/03 22:16:08 INFO ShuffleBlockFetcherIterator: Started 0 remote fetches in 4 ms
19/03/03 22:16:07 INFO TaskSetManager: Finished task 0.0 in stage 1.0 (TID 2) in 76 ms on localhost (executor driver) (1/2)
// 第二个分区比较 14 16 => 16(cat) ,14 66 => 66(tiger)
seqOp>>>>>  参数One:14--参数Two:16
seqOp>>>>>  参数One:14--参数Two:66
19/03/03 22:16:08 INFO ShuffleBlockFetcherIterator: Started 0 remote fetches in 4 ms
// 这个就是combOp阶段 在不同分区内 相同key的值做聚合操作 也就是(cat)14 + (cat)16 = 30 
combOp>>>>>  参数One:14--参数Two:16
// 最后结果 
结果数据>>>>>>>(dog,33)
结果数据>>>>>>>(cat,30)
19/03/03 22:16:08 INFO ShuffleBlockFetcherIterator: Started 0 remote fetches in 0 ms
结果数据>>>>>>>(tiger,66)
解析
一定要记住: combOp 是聚合的不同分区相同key的值

从上述过程中,我们就能明白流程是什么了。

  1. seqOp
    开始我们的数据是:
    分片1:(cat,3) (dog,33)
    分片2:(cat,16) (tiger,66)

     	// 这里只有两个分片 所以写两个过程 第一个分片开始seqOp过程:14(zeroValue) 和  3(cat) 比较  = 14(结果1),14(zeroValue) 和  33(dog) 比较  = 14(结果2)第二个分片开始元素聚合过程:14(zeroValue) 和  16(cat) 比较  = 14(结果3),14(zeroValue) 和  66(tiger) 比较  = 14(结果4)
    
  2. combOp(不同分区相同key值)

     	开始分片combOp过程:cat在不同分区有相同key值结果1  + 结果3 = 30(结果5)最终得到的结果2 ,结果4,结果5 结果数据>>>>>>>(dog,33)结果数据>>>>>>>(cat,30)结果数据>>>>>>>(tiger,66)
    

如果有什么不明白的评论留言即可。

这篇关于【SparkAPI JAVA版】JavaPairRDD——aggregateByKey(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/376446

相关文章

Spring实现Bean的初始化和销毁的方式

《Spring实现Bean的初始化和销毁的方式》:本文主要介绍Spring实现Bean的初始化和销毁的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Bean的初始化二、Bean的销毁总结在前面的章节当中介绍完毕了ApplicationContext,也就

Java的"伪泛型"变"真泛型"后对性能的影响

《Java的伪泛型变真泛型后对性能的影响》泛型擦除本质上就是擦除与泛型相关的一切信息,例如参数化类型、类型变量等,Javac还将在需要时进行类型检查及强制类型转换,甚至在必要时会合成桥方法,这篇文章主... 目录1、真假泛型2、性能影响泛型存在于Java源代码中,在编译为字节码文件之前都会进行泛型擦除(ty

Java中的getBytes()方法使用详解

《Java中的getBytes()方法使用详解》:本文主要介绍Java中getBytes()方法使用的相关资料,getBytes()方法有多个重载形式,可以根据需要指定字符集来进行转换,文中通过代... 目录前言一、常见重载形式二、示例代码三、getBytes(Charset charset)和getByt

Java使用Stream流的Lambda语法进行List转Map的操作方式

《Java使用Stream流的Lambda语法进行List转Map的操作方式》:本文主要介绍Java使用Stream流的Lambda语法进行List转Map的操作方式,具有很好的参考价值,希望对大... 目录背景Stream流的Lambda语法应用实例1、定义要操作的UserDto2、ListChina编程转成M

Spring框架中@Lazy延迟加载原理和使用详解

《Spring框架中@Lazy延迟加载原理和使用详解》:本文主要介绍Spring框架中@Lazy延迟加载原理和使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、@Lazy延迟加载原理1.延迟加载原理1.1 @Lazy三种配置方法1.2 @Component

使用easy connect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题

《使用easyconnect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题》:本文主要介绍使用easyconnect之后,maven无法... 目录使用easGWowCy connect之后,maven无法使用,原来需要配置-DJava.net.pr

idea报错java: 非法字符: ‘\ufeff‘的解决步骤以及说明

《idea报错java:非法字符:‘ufeff‘的解决步骤以及说明》:本文主要介绍idea报错java:非法字符:ufeff的解决步骤以及说明,文章详细解释了为什么在Java中会出现uf... 目录BOM是什么?1. BOM的作用2. 为什么会出现 \ufeff 错误?3. 如何解决 \ufeff 问题?最

使用Java编写一个字符脱敏工具类

《使用Java编写一个字符脱敏工具类》这篇文章主要为大家详细介绍了如何使用Java编写一个字符脱敏工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、字符脱敏工具类2、测试工具类3、测试结果1、字符脱敏工具类import lombok.extern.slf4j.Slf4j

Java实现按字节长度截取字符串

《Java实现按字节长度截取字符串》在Java中,由于字符串可能包含多字节字符,直接按字节长度截取可能会导致乱码或截取不准确的问题,下面我们就来看看几种按字节长度截取字符串的方法吧... 目录方法一:使用String的getBytes方法方法二:指定字符编码处理方法三:更精确的字符编码处理使用示例注意事项方

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约