在使用练习spark aggregate()函数时出现的问题。
其中aggregate()函数的作用是:aggregate()函数返回值类型不必与所操作的RDD类型相同。使用aggregate()时,需要提供我们期待返回的类型的初始值。然后通过一个函数把RDD中的元素合并起来放入累加器。考虑到每个节点是在本地进行累加的,最终,还需要提供第二个函数来将累加器两两合并。
public class Text implements Serializable {
//声明变量
public int total;
public int num;
//构造类
public Text(int total,int num){
this.total=total;this.num=num;
}
//求平均数方法
public double avg(){return total/(double)num;
}
//call中求初始化类中的值;如果Text(0,0)则a.total = 0 ,a.num = 0;如果Text(1,1)则a.total = 1,a.num = 1
static Function2<Text,Integer,Text> addAndCount=new Function2<Text, Integer, Text>() {
public Text call(Text a, Integer x) throws Exception {
a.total+=x;
a.num+=1;
return a;
}
};
//call中第一个类为第一个函数的返回值,第二个类为list的长度+初始化total;num的值等于list相加结果+初始化num
static Function2<Text,Text,Text> combine=new Function2<Text, Text, Text>() {
public Text call(Text a, Text b) throws Exception {
a.total+=b.total;
a.num+=b.num;
return a;
//这里的a 对象的值为:total:list的长度+第一个函数的total+初始化total
num : num的值+第一个函数的num+初始化num
};
public void static main(String args []){
SparkConf conf = new SparkConf().setAppName("Spark").setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
//初始化类 Text(total,num)
Text intial =new Text(0,0);//3.5 total : 1+2+3+4+5+6+0+0 num : list.size()+0+0
Text intial1 =new Text(1,2);//2.3 total : 1+2+3+4+5+6+1+1 num : list.size()+2+2
//将list或者set转换为RDD
JavaRDD<Integer> rdd7 =sc.parallelize(Arrays.asList(1, 2, 3, 4, 5, 6));Text result7=rdd7.aggregate(intial,addAndCount,combine);
System.out.println(result7.avg());
sc.close();
//如果类没有实现Serializable 接口则会报错,实现就可以了。
}
}
顺便普及一下Serializable 接口的作用:public interface Serializable类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
在我们自定义Text类中,需要实例化类 Text intial = Text(0,0);是报错,可见spark不能对其序列化。
所以当前类需要实现java.io.Serializable接口,那么spark就能使用java的ObjectOutStream来序列化当前类。