spark自定义累加器

package lcy.spark.sharedVariables.accumulators;
 
import org.apache.spark.SparkContext;
import org.apache.spark.api.java.function.MapFunction;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.util.AccumulatorV2;
 
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
 
/**
 * 自定义累加器
 * */
public class CustomAccumulatorDemo {
 
    // 需要注意的是累加操作不能依赖顺序,比如类似于StringAccumulator这种则会得到错误的结果
    public static class BigIntegerAccumulator extends AccumulatorV2<BigInteger, BigInteger> {
 
        private BigInteger num = BigInteger.ZERO;
 
        public BigIntegerAccumulator() {
        }
 
        public BigIntegerAccumulator(BigInteger num) {
            this.num = new BigInteger(num.toString());
        }
 
        @Override
        public boolean isZero() {
            return num.compareTo(BigInteger.ZERO) == 0;
        }
 
        @Override
        public AccumulatorV2<BigInteger, BigInteger> copy() {
            return new BigIntegerAccumulator(num);
        }
 
        @Override
        public void reset() {
            num = BigInteger.ZERO;
        }
 
        @Override
        public void add(BigInteger num) {
            this.num = this.num.add(num);
        }
 
        @Override
        public void merge(AccumulatorV2<BigInteger, BigInteger> other) {
            num = num.add(other.value());
        }
 
        @Override
        public BigInteger value() {
            return num;
        }
    }
 
    public static void main(String[] args) {
 
        SparkSession spark = SparkSession.builder().master("local[*]").getOrCreate();
        SparkContext sc = spark.sparkContext();
 
        // 直接new自定义的累加器
        BigIntegerAccumulator bigIntegerAccumulator = new BigIntegerAccumulator();
        // 然后在SparkContext上注册一下
        sc.register(bigIntegerAccumulator, "bigIntegerAccumulator");
 
        List<BigInteger> numList = Arrays.asList(new BigInteger("9999999999999999999999"), new BigInteger("9999999999999999999999"), new BigInteger("9999999999999999999999"));
        Dataset<BigInteger> num = spark.createDataset(numList, Encoders.kryo(BigInteger.class));
        Dataset<BigInteger> num2 = num.map((MapFunction<BigInteger, BigInteger>) x -> {
            bigIntegerAccumulator.add(x);
            return x;
        }, Encoders.kryo(BigInteger.class));
 
        num2.count();
        System.out.println("bigIntegerAccumulator: " + bigIntegerAccumulator.value());
 
    }
 
}

注意:

  • 在driver获取累加器的值用bigIntegerAccumulator.value

  • 在executor获取累加器的值用bigIntegerAccumulator

  • 累加器不会改变我们RDD的Lazy的特性,之后再Action之后完成计算和更新。

  • 但是假如出现两个Action公用一个转化操作,如map,在map里面进行累加器累加,那么每次action都会累加,造成某些我们不需要的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值