reduce和reduceByKey的区别

reduce和reduceByKey的区别
1、reduce:把RDD中的每一个元素拿出来处理并形成一个新的RDD元素

2、reduceByKey,把RDD中的key相同的一组数据拿出来处理,形成一个RDD里面放的是元组

reduce和reduceByKey是spark中使用地非常频繁的,在字数统计中,可以看到reduceByKey的经典使用。那么reduce和reduceBykey的区别在哪呢?reduce处理数据时有着一对一的特性,而reduceByKey则有着多对一的特性。比如reduce中会把数据集合中每一个元素都处理一次,并且每一个元素都对应着一个输出。而reduceByKey则不同,它会把所有key相同的值处理并且进行归并,其中归并的方法可以自己定义。

例子
在单词统计中,我们采用的就是reduceByKey,对于每一个单词我们设置成一个键值对(key,value),我们把单词作为key,即key=word,而value=1,因为遍历过程中,每个单词的出现一次,则标注1。那么reduceByKey则会把key相同的进行归并,然后根据我们定义的归并方法即对value进行累加处理,最后得到每个单词出现的次数。而reduce则没有相同Key归并的操作,而是将所有值统一归并,一并处理。

spark的reduce
我们采用scala来求得一个数据集中所有数值的平均值。该数据集包含5000个数值,数据集以及下列的代码均可从github下载,数据集名称为"avg"。为求得这个数据集中的平均值,我们先用map对文本数据进行处理,将其转换成long类型。

数据集内容:

reduce求平均值scala实现

import org.apache.spark.{SparkConf, SparkContext}

object SparkReduce {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("SparkReduce")

    val sc = new SparkContext(conf)

    //将String转成Long类型
    val numData = sc.textFile("./avg").map(num => num.toLong)

    //reduce处理每个值
    println(numData.reduce((x,y)=>{
      println("x:"+x)
      println("y:"+y)
      x+y
    })/numData.count())

  }

}

reduce求平均值Java实现

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;

public class SparkReduceJava {

    public static void main(String[] main){

        SparkConf conf = new SparkConf().setAppName("SparkReduceJava").setMaster("local");


        JavaSparkContext sc = new JavaSparkContext(conf);

        reduceJava(sc);

        reduceJava8(sc);
    }


    public static void reduceJava(JavaSparkContext sc){
        JavaRDD<Long>textData = sc.textFile("./avg").map(new Function<String, Long>() {
            @Override
            public Long call(String s) throws Exception {
                return Long.parseLong(s);
            };
        });

        System.out.println(
                textData.reduce(new Function2<Long, Long, Long>() {
                    @Override
                    public Long call(Long aLong, Long aLong2) throws Exception {
                        System.out.println("x:"+aLong);
                        System.out.println("y:"+aLong2);
                        return aLong+aLong2;
                    }
                })/textData.count()
        );
    }

    public static void reduceJava8(JavaSparkContext sc){
        JavaRDD<Long>textData = sc.textFile("./avg").map(s->Long.parseLong(s));
        System.out.println(textData.reduce((x,y)->x+y)/textData.count());
    }

}

spark的reduceByKey
spark的reduceByKey对要处理的值进行了差别对待,只有key相同的才能进行reduceByKey,则也就要求了进行reduceByKey时,输入的数据必须满足有键有值。由于上述的avg我们是用随机数生成的,那么我们可以用reduceByKey完成一个其他功能,即统计随机数中末尾是0-9各个数值出现的个数。
scala实现

import org.apache.spark.{SparkConf, SparkContext}

object SparkReduceByKey {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("SparkReduce")

    val sc = new SparkContext(conf)

    //将String转成Long类型
    val numData = sc.textFile("./avg").map(num => (num.toLong%10,1))

    numData.reduceByKey((x,y)=>x+y).foreach(println(_))
  }

}

java实现

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;

public class SparkReduceByKeyJava {

    public static void main(String[] main){

        SparkConf conf = new SparkConf().setAppName("SparkReduceJava").setMaster("local");


        JavaSparkContext sc = new JavaSparkContext(conf);

        reduceByKeyJava(sc);

        reduceByKeyJava8(sc);

    }


    public static void reduceByKeyJava(JavaSparkContext sc){

        JavaPairRDD<Integer,Integer> numData = sc.textFile("./avg").mapToPair(new PairFunction<String, Integer, Integer>() {
            @Override
            public Tuple2<Integer, Integer> call(String s) throws Exception {
                return new Tuple2<Integer, Integer>(Integer.parseInt(s)%10,1);
            }
        });


        System.out.println(numData.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer integer, Integer integer2) throws Exception {
                return integer+integer2;
            }
        }).collectAsMap());

    }

    public static void reduceByKeyJava8(JavaSparkContext sc){
        JavaPairRDD<Integer,Integer> numData = sc.textFile("./avg").mapToPair(s->new Tuple2<>(Integer.parseInt(s)%10,1));

        System.out.println(numData.reduceByKey((x,y)->x+y).collectAsMap());
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你在使用 `reduceByKey` 方法时遇到了报错,可能是因为你的 `sales` RDD 中的元素类型不是键值对类型。`reduceByKey` 方法只能用于键值对类型的 RDD,其中每个元素都是一个键值对。在这个例子中,我们使用 `map` 方法将 `sales` RDD 中的每个元素映射为一个新的三元组,但是这个三元组并不是键值对类型,因此不能直接使用 `reduceByKey` 方法。 要解决这个问题,你需要将三元组映射为键值对类型的 RDD,其中每个元素都是一个产品 ID 对应的销售额和利润。可以按照以下方式修改代码: ```scala val productSales = sales.map(x => (x._4, (x._5, x._7))).reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2)) ``` 在上面的代码中,我们首先将 `sales` RDD 中的每个元素映射为一个新的键值对类型的元组,其中第一个元素为产品 ID,第二个元素为一个包含销售额和利润的元组。接着,我们使用 `reduceByKey` 方法对键值对 RDD 进行聚合操作,将每个产品 ID 对应的销售额和利润分别相加,并返回一个新的键值对 RDD,其中每个键为产品 ID,每个值为一个包含销售额总和和利润总和的元组。 请注意,在使用 `reduceByKey` 方法时,需要传递一个函数作为参数,该函数将用于对键值对 RDD 中的每个键对应的值进行聚合操作。该函数需要接受两个参数,表示要聚合的两个值,并返回一个新的值。在这个例子中,我们使用了一个 lambda 函数来实现这个操作,该函数接受两个包含销售额和利润的元组作为参数,并返回一个新的包含销售额总和和利润总和的元组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值