史上最簡單的spark教程第六章-鍵值對RDD統計,JOIN連接的Java案例實踐-(上集)

第六章:鍵值對RDD的操作

  • 鍵值對RDD的操作用途:
    • 聚合,統計,分組

史上最簡單的spark教程
所有代碼示例地址:https://github.com/Mydreamandreality/sparkResearch

(提前聲明:文章由作者:張耀峯 結合自己生產中的使用經驗整理,最終形成簡單易懂的文章,寫作不易,轉載請註明)
(文章參考:Elasticsearch權威指南,Spark快速大數據分析文檔,Elasticsearch官方文檔,實際項目中的應用場景)
(幫到到您請點點關注,文章持續更新中!)
Git主頁 https://github.com/Mydreamandreality

  • 鍵值對的數據一般需要經過ETL,最終轉換成我們需要的數據
  • spark對鍵值對的RDD提供了一些新的接口,pairRDD
    • 提供並行操作各個鍵或跨節點重新進行數據分組的操作接口
    • 下面都是針對pairRDD的操作案例

現在這裏列舉一下pairRDD的常用函數,結合java案例代碼很好理解
操作數據:(以鍵值對集合{(1, 2), (3, 4), (3, 6)}爲例)

在這裏插入圖片描述

大概瞭解之後我們就可以直接看java代碼的案例了

pair RDD(鍵值對)的轉化操作
代碼示例:
    public static void run(JavaSparkContext sparkContext) {
        JavaRDD<String> rdd = sparkContext.parallelize(Arrays.asList("test", "java", "python"));

        
        //把RDD的第一個字符當做Key
        PairFunction<String, String, String> pairFunction = new PairFunction<String, String, String>() {
            @Override
            public Tuple2<String, String> call(String s) throws Exception {
                return new Tuple2<>(s.split(" ")[0], s);
            }
        };


        //此處創建好pairRDD
        JavaPairRDD<String, String> pairRdd = rdd.mapToPair(pairFunction);

        //下層都是對pairRDD的操作演示

        /*合併含有相同鍵的值*/
        pairRdd.reduceByKey(new Function2<String, String, String>() {
            @Override
            public String call(String v1, String v2) throws Exception {
                return v1 + v2;
            }
        });

        /*相同key的元素進行分組*/
        pairRdd.groupByKey();

        /*對pair中的每個值進行應用*/
        pairRdd.mapValues(new Function<String, Object>() {
            @Override
            public Object call(String v1) throws Exception {
                return v1 + "sirZ";
            }
        });

        /*返回只包含鍵的RDD*/
        pairRdd.keys();

        /*返回只包含值的RDD*/
        pairRdd.values();

        /*返回根據鍵排序的RDD*/
        pairRdd.sortByKey();

    }

上面的案例是針對單個RDD元素進行操作
這裏就針對兩個RDD進行操作 (可以理解爲MySQL表連接?我不知道是否可以這麼理解)
代碼示例
/**
 * Created by 張燿峯
 * pairRDD入門案例
 *
 * @author 孤
 * @date 2019/3/19
 * @Varsion 1.0
 */
public class PairRdd {

    public static void run(JavaSparkContext sparkContext) {
        JavaRDD<String> rdd = sparkContext.parallelize(Arrays.asList("test", "java", "python"));


        PairFunction<String, String, String> pairFunction = new PairFunction<String, String, String>() {
            @Override
            public Tuple2<String, String> call(String s) throws Exception {
                return new Tuple2<>(s.split(" ")[0], s);
            }
        };


        //此處創建好pairRDD
        JavaPairRDD<String, String> pairRdd = rdd.mapToPair(pairFunction);

        //下層都是對pairRDD的操作演示

        /*合併含有相同鍵的值*/
        pairRdd.reduceByKey(new Function2<String, String, String>() {
            @Override
            public String call(String v1, String v2) throws Exception {
                return v1 + v2;
            }
        });

        /*相同key的元素進行分組*/
        pairRdd.groupByKey();

        /*對pair中的每個值進行應用*/
        pairRdd.mapValues(new Function<String, Object>() {
            @Override
            public Object call(String v1) throws Exception {
                return v1 + "sirZ";
            }
        });

        /*返回只包含鍵的RDD*/
        pairRdd.keys();

        /*返回只包含值的RDD*/
        pairRdd.values();

        /*返回根據鍵排序的RDD*/
        pairRdd.sortByKey();

    }

    /*針對多個pairRDD元素的操作*/
    public static void runPair(JavaSparkContext sparkContext) {

        JavaRDD<String> rdd = sparkContext.parallelize(Arrays.asList("test", "java", "python"));
        JavaRDD<String> otherRDD = sparkContext.parallelize(Arrays.asList("golang", "php", "hadoop"));

        PairFunction<String, String, String> pairFunction = new PairFunction<String, String, String>() {
            @Override
            public Tuple2<String, String> call(String s) {
                return new Tuple2<>(s.split(" ")[0], s);
            }
        };
        JavaPairRDD<String, String> pairRDD = rdd.mapToPair(pairFunction);
        JavaPairRDD<String, String> pairRDDOther = otherRDD.mapToPair(pairFunction);

        //創建好兩個PairRDD之後開始操作

        //刪除 ==pairRDD== 中鍵與pairRDDOther相同的元素
        JavaPairRDD<String, String> subRDD = pairRDD.subtractByKey(pairRDDOther);

        //內連接 inner join 查詢
        JavaPairRDD<String, Tuple2<String, String>> jsonRDD = pairRDD.join(pairRDDOther);

        //右連接 right join 查詢   //TODO 此處我理解是可以爲null的二元組
        JavaPairRDD<String, Tuple2<Optional<String>, String>> rightRDD = pairRDD.rightOuterJoin(pairRDDOther);

        //左連接 left join 查詢
        JavaPairRDD<String, Tuple2<String, Optional<String>>> leftRDD = pairRDD.leftOuterJoin(pairRDDOther);

        //將兩個RDD中有相同鍵的數據分組  //TODO 此處我理解是迭代器
        JavaPairRDD<String, Tuple2<Iterable<String>, Iterable<String>>> groupRDD = pairRDD.cogroup(pairRDDOther);


    }

以上就是spark鍵值對的操作簡單案例
首先創建pariRDD(鍵值對RDD),然後對創建好的PairRDD進行操作
具體的使用看代碼中註釋,後續還會有更深入的案例

此處需要注意一下: PairRDD也還是RDD組,同樣支持RDD所支持的函數
代碼案例:
         //pairRDD也可以使用RDD的函數
        //篩選length小於20的元素
        Function<Tuple2<String,String>,Boolean> filterRDD = new Function<Tuple2<String, String>, Boolean>() {
            @Override
            public Boolean call(Tuple2<String, String> v1) {
                return (v1._2.length()<20);
            }
        };
        JavaPairRDD<String,String> filter = pairRDD.filter(filterRDD);

聚合操作
當數據集以鍵值對形式組織的時候,聚合具有相同鍵的元素進行一些統計是很常見的操作,之前說過基礎 RDD上的 fold(),combine(),reduce() 等行動操作,pair RDD 上則有相應的針對鍵的轉化操作.Spark 有一組類似的操作,可以組合具有相同鍵的值,這些操作返回 RDD,因此它們是轉化操作而不是行動操作
代碼案例
JavaRDD<String> wordCount = sparkContext.parallelize(Arrays.asList("1", "2", "3", "4", "5"));

        //返回一個可以迭代的集合
        JavaRDD<String> c = wordCount.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public Iterator<String> call(String v1) throws Exception {
                return Arrays.asList(v1.split(" ")).iterator();
            }
        });

        //現在的數據是 1,2,3,4,5
        JavaPairRDD<String, Integer> result = c.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String s) throws Exception {
                return new Tuple2<>(s, 1);
                //此時的數據是 {1,1},{2,1},{3,1},{4,1}...
            }
        }).reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1 + v2;
            }
        });

        /*還可以通過countByValue快速實現單詞計數*/
        c.countByValue();
總結
pairRDD(鍵值對RDD)
有很多函數可以進行基於鍵的數據合併,它們中的大多數都是在 combineByKey() 的基礎上實現的,爲用戶提供了更簡單的接口
combineByKey()的工作原理如下:

在這裏插入圖片描述

本人純手工畫的,見諒 [狗頭]

下一章會寫一些pairRDD的行動操作和數據分區等高級概念

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