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); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。