Spark中Transformation的講解

主要講解一下
map,filter,flatMap,groupByKey,reduceByKey,sortByKey,join,cogroup

map講解

List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        JavaRDD<Integer> line=sc.parallelize(list);
        // 使用map算子,將集合中的每個元素都乘以2
        // map算子,是對任何類型的RDD,都可以調用的
        // 在java中,map算子接收的參數是Function對象
        // 創建的Function對象,一定會讓你設置第二個泛型參數,這個泛型類型,就是返回的新元素的類型
        // 同時call()方法的返回類型,也必須與第二個泛型類型同步
        // 在call()方法內部,就可以對原始RDD中的每一個元素進行各種處理和計算,並返回一個新的元素
        // 所有新的元素就會組成一個新的RDD
        JavaRDD<Integer> lineM=line.map(new Function<Integer, Integer>() {
            @Override
            public Integer call(Integer i) throws Exception {
                return i*2;
            }
        });

filter講解

// 對初始RDD執行filter算子,過濾出其中的偶數
            // filter算子,傳入的也是Function,其他的使用注意點,實際上和map是一樣的
            // 但是,唯一的不同,就是call()方法的返回類型是Boolean
            // 每一個初始RDD中的元素,都會傳入call()方法,此時你可以執行各種自定義的計算邏輯
            // 來判斷這個元素是否是你想要的
            // 如果你想在新的RDD中保留這個元素,那麼就返回true;否則,不想保留這個元素,返回false
            JavaRDD<Integer> lineeven=line.filter(new Function<Integer, Boolean>() {
                @Override
                public Boolean call(Integer i) throws Exception {
                    return i%2==0;
                }
            });

flatMap講解

 List<String> lists= Arrays.asList("hello you","hello me");
            JavaRDD<String> linestring=sc.parallelize(lists);
            // 對RDD執行flatMap算子,將每一行文本,拆分爲多個單詞
            // flatMap算子,在java中,接收的參數是FlatMapFunction
            // 我們需要自己定義FlatMapFunction的第二個泛型類型,即,代表了返回的新元素的類型
            // call()方法,返回的類型,不是U,而是Iterable<U>,這裏的U也與第二個泛型類型相同
            // flatMap其實就是,接收原始RDD中的每個元素,並進行各種邏輯的計算和處理,返回可以返回多個元素
            // 多個元素,即封裝在Iterable集合中,可以使用ArrayList等集合
            // 新的RDD中,即封裝了所有的新元素;也就是說,新的RDD的大小一定是 >= 原始RDD的大小
            JavaRDD<String> lines=linestring.flatMap(new FlatMapFunction<String, String>() {
                @Override
                public Iterable<String> call(String s) throws Exception {
                    return Arrays.asList(s.split(" "));
                }
            });

groupByKey講解

List<Tuple2<String,Integer>> sorce=Arrays.asList(new Tuple2<String, Integer>("one",85),
                    new Tuple2<String, Integer>("two",95),
                    new Tuple2<String, Integer>("one",90),
                    new Tuple2<String, Integer>("two",70)
            );

            // 針對scores RDD,執行groupByKey算子,對每個班級的成績進行分組
            // groupByKey算子,返回的還是JavaPairRDD
            // 但是,JavaPairRDD的第一個泛型類型不變,第二個泛型類型變成Iterable這種集合類型
            // 也就是說,按照了key進行分組,那麼每個key可能都會有多個value,此時多個value聚合成了Iterable
            // 那麼接下來,我們是不是就可以通過so這種JavaPairRDD,很方便地處理某個分組內的數據
            JavaPairRDD<String,Integer> sorces=sc.parallelizePairs(sorce);
            JavaPairRDD<String,Iterable<Integer>> so=sorces.groupByKey();
            so.foreach(new VoidFunction<Tuple2<String, Iterable<Integer>>>() {
                @Override
                public void call(Tuple2<String, Iterable<Integer>> s) throws Exception {
                    System.out.println("key is:"+s._1);
                    Iterator<Integer> s1=s._2.iterator();
                    int sum=0;
                    while(s1.hasNext()){
                        sum=sum+s1.next();
                    }
                    System.out.println(sum);
                }
            });

reduceByKey講解

// 針對sorces RDD,執行reduceByKey算子
            // reduceByKey,接收的參數是Function2類型,它有三個泛型參數,實際上代表了三個值
            // 第一個泛型類型和第二個泛型類型,代表了原始RDD中的元素的value的類型
            // 因此對每個key進行reduce,都會依次將第一個、第二個value傳入,將值再與第三個value傳入
            // 因此此處,會自動定義兩個泛型類型,代表call()方法的兩個傳入參數的類型
            // 第三個泛型類型,代表了每次reduce操作返回的值的類型,默認也是與原始RDD的value類型相同的
            // reduceByKey算法返回的RDD,還是JavaPairRDD<key, value>

            sorces.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    // 對每個key,都會將其value,依次傳入call方法
                    // 從而聚合出每個key對應的一個value
                    // 然後,將每個key對應的一個value,組合成一個Tuple2,作爲新RDD的元素
                    return v1+v2;
                }
            }).foreach(new VoidFunction<Tuple2<String, Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> s) throws Exception {
                    System.out.println(s._1+"==="+s._2);
                }
            });

sortByKey講解

// 對scores RDD執行sortByKey算子
            // sortByKey其實就是根據key進行排序,可以手動指定升序,或者降序
            // 返回的,還是JavaPairRDD,其中的元素內容,都是和原始的RDD一模一樣的
            // 但是就是RDD中的元素的順序,不同了

            //sorces 是PairRDD。我們需要先將key和value互換,在排序以後z,排序以後在將key value互換。
           sorces.mapToPair(new PairFunction<Tuple2<String,Integer>, Integer, String>() {
                @Override
                public Tuple2<Integer, String> call(Tuple2<String, Integer> t) throws Exception {
                    return Tuple2.apply(t._2,t._1);
                }
            }).sortByKey(false,1).mapToPair(new PairFunction<Tuple2<Integer,String>, String, Integer>() {
                @Override
                public Tuple2<String, Integer> call(Tuple2<Integer, String> t) throws Exception {
                    return Tuple2.apply(t._2,t._1);
                }
            }).foreach(new VoidFunction<Tuple2<String, Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> s) throws Exception {
                    System.out.println(s._1+"==="+s._2);
                }
            });

join講解

List<Tuple2<Integer,String>> student=Arrays.asList(new Tuple2<Integer, String>(1,"xlucas1"),
                    new Tuple2<Integer, String>(2,"xlucas2"),
                    new Tuple2<Integer, String>(3,"xlucas3"));
            List<Tuple2<Integer,Integer>> scorea=Arrays.asList(
                    new Tuple2<Integer, Integer>(1,90),
                    new Tuple2<Integer, Integer>(2,80),
                    new Tuple2<Integer, Integer>(3,100),
                    new Tuple2<Integer, Integer>(1,100)
            );
            JavaPairRDD<Integer,String> s1=sc.parallelizePairs(student);
            JavaPairRDD<Integer,Integer> s2=sc.parallelizePairs(scorea);
            // 使用join算子關聯兩個RDD
            // join以後,還是會根據key進行join,並返回JavaPairRDD
            // 但是JavaPairRDD的第一個泛型類型,之前兩個JavaPairRDD的key的類型,因爲是通過key進行join的
            // 第二個泛型類型,是Tuple2<v1, v2>的類型,Tuple2的兩個泛型分別爲原始RDD的value的類型
            // join,就返回的RDD的每一個元素,就是通過key join上的一個pair
            // 什麼意思呢?比如有(1, 1) (1, 2) (1, 3)的一個RDD
            // 還有一個(1, 4) (2, 1) (2, 2)的一個RDD
            // join以後,實際上會得到(1 (1, 4)) (1, (2, 4)) (1, (3, 4))
            s1.join(s2).foreach(new VoidFunction<Tuple2<Integer, Tuple2<String, Integer>>>() {
                @Override
                public void call(Tuple2<Integer, Tuple2<String, Integer>> t) throws Exception {
                    System.out.println("id="+t._1);
                    System.out.println("name="+t._2._1);
                    System.out.println("id="+t._2._2);
                }
            });

cogroup講解

// cogroup與join不同
            // 相當於是,一個key join上的所有value,都給放到一個Iterable裏面去了
            s1.cogroup(s2).foreach(new VoidFunction<Tuple2<Integer, Tuple2<Iterable<String>, Iterable<Integer>>>>() {
                @Override
                public void call(Tuple2<Integer, Tuple2<Iterable<String>, Iterable<Integer>>> t) throws Exception {
                    System.out.println("id="+t._1);
                    System.out.println("name="+t._2._1);
                    System.out.println("id="+t._2._2);
                }
            });

更多信息可以關注訂閱號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章