Spark 算子Java操作示例。

Spark中有许许多多的算子来支持各种操作,但其中主要分为两种;一种就是Transformations算子,一种是Action算子。官方文档中已经指出了常用的算子。好记性不如烂笔头,在这里记录一下各个算子的作用以及使用方法。

Transformations算子:顾名思义,这种算子的作用就是将一个RDD转换成另一种RDD,有的算子转换过程中还会涉及到parition的变化和Shuffle操作,这里只介绍算子的使用方法,其中的parition和shuffle的具体变换可能不会提到。

Action算子:该算子会触发一个runJob操作,也就是只有使用了Action算子才会将程序提交到集群进行计算,最后会得到一个结果。


SparkConf和JavaSparkContext的初始化。

SparkConf conf = new SparkConf().setMaster("local").setAppName("TransformationsOperator");
JavaSparkContext sc = new JavaSparkContext(conf);

1 . map(func)。

官方介绍:

Return a new distributed dataset formed by passing each element of the source through a function func.

通过函数将RDD中的每个元素进行转换形成一个新的RDD。

操作示例:

    // map,一次只处理一个parition中的一条数据。
    private static void MapOperator(JavaSparkContext sc) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        JavaRDD<Integer> numberRDD = sc.parallelize(numbers);// 得到一个RDD

        JavaRDD<String> results = numberRDD.map(new Function<Integer, String>() {
  //使用map操作将Integer类型转换成String

            private static final long serialVersionUID = 1L;

            @Override
            public String call(Integer number) throws Exception {

                return "number:" + number;
            }

        });

        results.foreach(new VoidFunction<String>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void call(String arg0) throws Exception {
                System.out.println(arg0);
            }
        });
    }

2.mapPartitions(func)。

官方介绍:

Similar to map, but runs separately on each partition (block) of the RDD, so func must be of type Iterator => Iterator when running on an RDD of type T.

作用于map一致,不过是以每个parition作为一个操作单位的,所以返回类型是一个Iterator。

操作示例:

// mapPartitions,这个是针对Partition的操作,一次会处理一个partition的所有数据
    private static void MapPartitionsOperator(JavaSparkContext sc) {

        List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu");

        JavaRDD<String> nameRDD = sc.parallelize(names,2);

        final Map<String, Integer> scoreMap = new HashMap<>();
        scoreMap.put("zhangsan", 100);
        scoreMap.put("lisi", 99);
        scoreMap.put("wangwu", 98);

        //这里会使用FlatMapFunction将Iterator中的数据自动压缩成Integer数据。
        JavaRDD<Integer> scoreRDD = nameRDD.mapPartitions(new FlatMapFunction<Iterator<String>, Integer>() {

            private static final long serialVersionUID = 1L;

            @Override
            public Iterator<Integer> call(Iterator<String> iterator) throws Exception {
                List<Integer> scores = new ArrayList<>();
                while (iterator.hasNext()) {
                    String name = iterator.next();
                    int score = scoreMap.get(name);
                    scores.add(score);
                }
                return scores.iterator();
            }
        });

        scoreRDD.foreach(new VoidFunction<Integer>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void call(Integer score) throws Exception {
                System.out.println(score);
            }
        });

    }

可以通过FlatMapFunction的参数看到,第一个是Iterator< String>的,也就是输入的数据是一个Iterator,输出的是Integer,这个输入的 Iterator就是将一个partition中的所有数据传入进来,经过操作后变成一个Iterator< Integer>的,然后在自动压缩成Integer。


3 . mapPartitionsWithIndex(func)。

官方介绍:

Similar to mapPartitions, but also provides func with an integer value representing the index of the partition, so func must be of type (Int, Iterator) => Iterator when running on an RDD of type T.

与上述的mapParitions神似,不过每次调用call函数的时候会传入一个当前parition的下标进来。

操作示例:

// 可以看到使用了哪一个parition,采用分区的话:parallelize优先级最高,其次conf.set,最后时local[];
    private static void MapPartitionsWithIndexOperator(JavaSparkContext sc) {
        List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu");

        JavaRDD<String> nameRDD = sc.parallelize(names, 2);//这里加载的数据设置成2个partition。

        JavaRDD<String> results = nameRDD
                .mapPartitionsWithIndex(new Function2<Integer, Iterator<String>, Iterator<String>>() {

                    private static final long serialVersionUID = 1L;
                    //这里会有一个Integer的index,可以通过这个来查看当前操作属于哪一个parition。
                    @Override
                    public Iterator<String> call(Integer index, Iterator<String> names) throws Exception {
                        List<String> nameList = new ArrayList<>();

                        while (names.hasNext()) {
                            String name = names.next();
                            name = index + ":" + name;
                            nameList.add(name);
                        }

                        return nameList.iterator();
                    }
                }, true);

        results.foreach(new VoidFunction<String>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void call(String name) throws Exception {
                System.out.println(name);
            }
        });

    }

4.filter(func)。

官方介绍:

Return a new dataset formed by selecting those elements of the source on which func returns true.

也就是通过函数筛选出所需要的数据元素,返回true也代表保留,false代表抛弃。

操作示例:

// 过滤出一部分数据
    private static void FilterOperator(JavaSparkContext sc) {
        List<Integer> scores = Arrays.asList(43, 60, 59, 70, 81);
        JavaRDD<Integer> scoresRDD = sc.parallelize(scores);

        //筛选出分数小于60的。
        JavaRDD<Integer> results = scoresRDD.filter(new Function<Integer, Boolean>() {

            private static final long serialVersionUID = 1L;

            @Override
            public Boolean call(Integer score) throws Exception {

                return score < 60;
            }
        });

        results.foreach(new VoidFunction<Integer>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void call(Integer score) throws Exception {
                System.out.println(score);
            }
        });

    }

5.coalesce(numPartitions)。

官方介绍:

Decrease the number of partitions in the RDD to numPartitions. Useful for running operations more efficiently after filtering down a large dataset.

将RDD中的partition进行减少,尤其是在上述的filter之后使用效果更好,因为filter会可能会过滤掉大量的数据从而导致一个partition中的数据量很少,这时候使用coalesce算子可以尽量的合并partition,一定程度少减少数据倾斜的问题。

操作示例:

// 将partition的数量减少
    private static void CoalesceOperator(JavaSparkContext sc) {
        List<String> students = Arrays.asList("stu1", "stu2", "stu3", "stu4", "stu5", "stu6");
        JavaRDD<String> cls = sc.parallelize(students, 4);// 设置为四个partition

        JavaRDD<String> temp = cls.mapPartitionsWithIndex(new Function2<Integer, Iterator<String>, Iterator<String>>() {

            private static final long serialVersionUID = 1L;

            @Override
            public Iterator<String> call(Integer index, Iterator<String> cls) throws Exception {
                List<String> list = new ArrayList<>();

                while (cls.hasNext()) {
                    String stu = cls.next();
                    stu = "1[" + index + "]" + stu;
                    list.add(stu);
                }

                return list.iterator();
            }
        }, true);

        JavaRDD<String> temp2 = temp.coalesce(2);//将四个partition减少到两个

        JavaRDD<String> result = temp2
                .mapPartitionsWithIndex
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值