欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java8 Collectors求和功能的自定义扩展操作

程序员文章站 2022-03-27 07:54:11
业务中需要将一组数据分类后收集总和,原本可以使用collectors.summingint(),但是我们的数据源是bigdecimal类型的,而java8原生只提供了summingint、summin...

业务中需要将一组数据分类后收集总和,原本可以使用collectors.summingint(),但是我们的数据源是bigdecimal类型的,而java8原生只提供了summingint、summinglong、summingdouble三种基础类型的方法。

于是就自己动手丰衣足食吧。。

自定义工具类

public class mycollectors {
  private mycollectors() {
  }
//  public static <t> collector<t, ?, bigdecimal> summingbigdecimal(function<? super t, bigdecimal> mapper) {}
 	// bigdecimal 类型的集合求和
  public static <t> collector<t, ?, bigdecimal> summingbigdecimal(tobigdecimalfunction<? super t> mapper) {
    return new collectorimpl<>(
        () -> new bigdecimal[] { bigdecimal.zero },
        (a, t) -> a[0] = a[0].add(mapper.applyasint(t)),
        (a, b) -> {
          a[0] = a[0].add(b[0]);
          return a;
        },
        a -> a[0],
        collections.emptyset()
    );
  }
  static class collectorimpl<t, a, r> implements collector<t, a, r> {
    // 创建一个计算用的容器
    private final supplier<a> supplier;
    // 计算逻辑
    private final biconsumer<a, t> accumulator;
    // 合并逻辑
    private final binaryoperator<a> combiner;
    // 返回最终计算值
    private final function<a, r> finisher;
    // 空set
    private final set<characteristics> characteristics;
    collectorimpl(supplier<a> supplier, biconsumer<a, t> accumulator, binaryoperator<a> combiner,
           function<a, r> finisher, set<characteristics> characteristics) {
      this.supplier = supplier;
      this.accumulator = accumulator;
      this.combiner = combiner;
      this.finisher = finisher;
      this.characteristics = characteristics;
    }
    collectorimpl(supplier<a> supplier, biconsumer<a, t> accumulator, binaryoperator<a> combiner,
           set<characteristics> characteristics) {
      this(supplier, accumulator, combiner, castingidentity(), characteristics);
    }
    @override
    public biconsumer<a, t> accumulator() {
      return accumulator;
    }
    @override
    public supplier<a> supplier() {
      return supplier;
    }
    @override
    public binaryoperator<a> combiner() {
      return combiner;
    }
    @override
    public function<a, r> finisher() {
      return finisher;
    }
    @override
    public set<characteristics> characteristics() {
      return characteristics;
    }
  }
  @suppresswarnings("unchecked")
  private static <i, r> function<i, r> castingidentity() {
    return i -> (r) i;
  }
}

自定义函数式接口

@functionalinterface
public interface tobigdecimalfunction<t> {
  bigdecimal applyasint(t value);
}

测试入口

public class answerapp {
 public static void main(string[] args) {
    list<bigdecimal> list = lists.newarraylist();
    for (int i = 0; i < 24; i++) {
      list.add(bigdecimal.valueof(i + 10.2121543));
    }
    // 方式1
    bigdecimal sum = list.stream().collect(mycollectors.summingbigdecimal(e -> e));
    system.out.println(sum.doublevalue());
    // 方式2
    optional<bigdecimal> reduce = list.stream().reduce(bigdecimal::add);
    system.out.println(reduce.orelse(bigdecimal.valueof(0)));
 }    
}
// output: 521.0917032

补充:collectors扩展接口 实现bigdecimal的相加

第一步

创建tobigdecimalfunction接口

import java.math.bigdecimal;
@functionalinterface
public interface tobigdecimalfunction<t> {
  bigdecimal applyasbigdecimal(t value);
}

第二步

创建工具类 实现接口

import java.math.bigdecimal;
import java.util.collections;
import java.util.set;
import java.util.function.biconsumer;
import java.util.function.binaryoperator;
import java.util.function.function;
import java.util.function.supplier;
import java.util.stream.collector;
public class collectorsutil {
  static final set<collector.characteristics> ch_noid = collections.emptyset();
  private collectorsutil() {
  }
  @suppresswarnings("unchecked")
  private static <i, r> function<i, r> castingidentity() {
    return i -> (r) i;
  }
  /**
   * simple implementation class for {@code collector}.
   *
   * @param <t>
   *      the type of elements to be collected
   * @param <r>
   *      the type of the result
   */
  static class collectorimpl<t, a, r> implements collector<t, a, r> {
    private final supplier<a> supplier;
    private final biconsumer<a, t> accumulator;
    private final binaryoperator<a> combiner;
    private final function<a, r> finisher;
    private final set<characteristics> characteristics;
    collectorimpl(supplier<a> supplier, biconsumer<a, t> accumulator, binaryoperator<a> combiner,
           function<a, r> finisher, set<characteristics> characteristics) {
      this.supplier = supplier;
      this.accumulator = accumulator;
      this.combiner = combiner;
      this.finisher = finisher;
      this.characteristics = characteristics;
    }
    collectorimpl(supplier<a> supplier, biconsumer<a, t> accumulator, binaryoperator<a> combiner,
           set<characteristics> characteristics) {
      this(supplier, accumulator, combiner, castingidentity(), characteristics);
    }
    @override
    public biconsumer<a, t> accumulator() {
      return accumulator;
    }
    @override
    public supplier<a> supplier() {
      return supplier;
    }
    @override
    public binaryoperator<a> combiner() {
      return combiner;
    }
    @override
    public function<a, r> finisher() {
      return finisher;
    }
    @override
    public set<characteristics> characteristics() {
      return characteristics;
    }
  }
  public static <t> collector<t, ?, bigdecimal> summingbigdecimal(tobigdecimalfunction<? super t> mapper) {
    return new collectorimpl<>(() -> new bigdecimal[1], (a, t) -> {
      if (a[0] == null) {
        a[0] = bigdecimal.zero;
      }
      a[0] = a[0].add(mapper.applyasbigdecimal(t));
    }, (a, b) -> {
      a[0] = a[0].add(b[0]);
      return a;
    }, a -> a[0], ch_noid);
  }
}

使用测试

import com.example.javademo.javademoapplicationtests;
import com.example.javademo.pojo.student;
import com.example.javademo.utils.datautils;
import org.junit.test;
import java.math.bigdecimal;
import java.util.stream.collectors;
public class testbigdecimal extends javademoapplicationtests {
  @test
  public void testgroupbyafterbigdecimal(){
    /*
    自定义实现对分组后的集合,属性为bigdecmal进行相加
     */
    system.out.println(datautils.getdata().stream().collect(collectors.groupingby(student::getschool,collectorsutil.summingbigdecimal(student::getmoney))));
    //归约造作
    bigdecimal reduce = datautils.getdata().stream().map(student::getmoney).reduce(bigdecimal.zero, bigdecimal::add);
    system.out.println(reduce);
    int sum = datautils.getdata().stream().maptoint(student::getage).sum();
    system.out.println(sum);
  }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。