好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

自定义工具类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

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 测试数据biner = 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;

   }

}

自定义函数式接口

?

1

2

3

4

@FunctionalInterface

public interface ToBigDecimalFunction<T> {

   BigDecimal applyAsInt(T value);

}

测试入口

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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接口

?

1

2

3

4

5

import java.math.BigDecimal;

@FunctionalInterface

public interface ToBigDecimalFunction<T> {

   BigDecimal applyAsBigDecimal(T value);

}

第二步

创建工具类 实现接口

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

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 测试数据biner = 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);

   }

}

使用测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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);

   }

}

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

原文链接:https://jaemon.blog.csdn.net/article/details/103405970

查看更多关于Java8 Collectors求和功能的自定义扩展操作的详细内容...

  阅读:32次