对一个List进行分组汇总的lambada写法:
list.stream().collect(Collectors.groupingBy(TestDTO::getId, Collectors.summarizingInt(TestDTO::getValue)));
上面TestDTO::getValue是进行整形汇总,但是如果TestDTO::getValue是BigDecimal类型的怎么办,写法如下:
list.stream().collect(Collectors.groupingBy(TestDTO::getId, Collectors.reducing(BigDecimal.ZERO, TestDTO::getValue, BigDecimal::add)));
多个list合并成一个list
比如有下面数据结构:
List<List<String>> list = new ArrayList<>();
List<String> sub1 = new ArrayList<>();
sub1.add("1111");
sub1.add("2222");
sub1.add("3333");
sub1.add("4444");
list.add(sub1);
List<String> sub2 = new ArrayList<>();
sub2.add("aaaa");
sub2.add("bbbb");
sub2.add("cccc");
sub2.add("dddd");
list.add(sub2);
List<String> sub3 = new ArrayList<>();
sub3.add("a001");
sub3.add("b002");
sub3.add("c003");
sub3.add("d004");
list.add(sub3);
合并成一个List的写法:
List<String> myList = list.stream().flatMap(Collection::stream).collect(Collectors.toList());
求平均值:
list.stream().collect(Collectors.groupingBy(TestDTO::getId, Collectors.averagingInt(TestDTO::getValue)));
如果TestDTO::getValue是BigDecimal类型的,则不能这么用,需要自己写一个工具类:
1 @FunctionalInterface
2 public interface ToBigDecimalFunction<T> {
3
4 BigDecimal applyAsBigDecimal(T value);
5 }
1 public final class CustomCollectors {
2
3 private static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
4
5 private CustomCollectors() {}
6
7
8 @SuppressWarnings("unchecked")
9 private static <I, R> Function<I, R> castingIdentity() {
10 return i -> (R) i;
11 }
12
13 /**
14 * Simple implementation class for {@code Collector}.
15 *
16 * @param <T> the type of elements to be collected
17 * @param <R> the type of the result
18 */
19 @SuppressWarnings("hiding")
20 static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
21 private final Supplier<A> supplier;
22 private final BiConsumer<A, T> accumulator;
23 private final BinaryOperator<A> combiner;
24 private final Function<A, R> finisher;
25 private final Set<Characteristics> characteristics;
26
27 CollectorImpl(Supplier<A> supplier,
28 BiConsumer<A, T> accumulator,
29 BinaryOperator<A> combiner,
30 Function<A,R> finisher,
31 Set<Characteristics> characteristics) {
32 this.supplier = supplier;
33 this.accumulator = accumulator;
34 this.combiner = combiner;
35 this.finisher = finisher;
36 this.characteristics = characteristics;
37 }
38
39 CollectorImpl(Supplier<A> supplier,
40 BiConsumer<A, T> accumulator,
41 BinaryOperator<A> combiner,
42 Set<Characteristics> characteristics) {
43 this(supplier, accumulator, combiner, castingIdentity(), characteristics);
44 }
45
46 @Override
47 public BiConsumer<A, T> accumulator() {
48 return accumulator;
49 }
50
51 @Override
52 public Supplier<A> supplier() {
53 return supplier;
54 }
55
56 @Override
57 public BinaryOperator<A> combiner() {
58 return combiner;
59 }
60
61 @Override
62 public Function<A, R> finisher() {
63 return finisher;
64 }
65
66 @Override
67 public Set<Characteristics> characteristics() {
68 return characteristics;
69 }
70 }
71
72 //求和方法
73 public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
74 return new CollectorImpl<>(
75 () -> new BigDecimal[]{new BigDecimal(0)},
76 (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t), MathContext.DECIMAL32); },
77 (a, b) -> { a[0] = a[0].add(b[0], MathContext.DECIMAL32) ; return a; },
78 a -> a[0], CH_NOID);
79 }
80
81
82 //求最大,这里的最小MIN值,作为初始条件判断值,如果某些数据范围超过百亿以后,可以根据需求换成Long.MIN_VALUE或者Double.MIN_VALUE
83 public static <T> Collector<T, ?, BigDecimal> maxBy(ToBigDecimalFunction<? super T> mapper) {
84 return new CollectorImpl<>(
85 () -> new BigDecimal[]{new BigDecimal(Integer.MIN_VALUE)},
86 (a, t) -> { a[0] = a[0].max(mapper.applyAsBigDecimal(t)); },
87 (a, b) -> { a[0] = a[0].max(b[0]) ; return a; },
88 a -> a[0], CH_NOID);
89 }
90
91 //求最小,这里的最大MAX值,作为初始条件判断值,如果某些数据范围超过百亿以后,可以根据需求换成Long.MAX_VALUE或者Double.MAX_VALUE
92 public static <T> Collector<T, ?, BigDecimal> minBy(ToBigDecimalFunction<? super T> mapper) {
93 return new CollectorImpl<>(
94 () -> new BigDecimal[]{new BigDecimal(Integer.MAX_VALUE)},
95 (a, t) -> { a[0] = a[0].min(mapper.applyAsBigDecimal(t)); },
96 (a, b) -> { a[0] = a[0].min(b[0]) ; return a; },
97 a -> a[0], CH_NOID);
98 }
99
100 /**
101 * 返回一个平均值
102 * @param newScale 保留小数位数
103 * @param roundingMode 小数处理方式
104 * #ROUND_UP 进1
105 * #ROUND_DOWN 退1
106 * #ROUND_CEILING 进1截取:正数则ROUND_UP,负数则ROUND_DOWN
107 * #ROUND_FLOOR 退1截取:正数则ROUND_DOWN,负数则ROUND_UP
108 * #ROUND_HALF_UP >=0.5进1
109 * #ROUND_HALF_DOWN >0.5进1
110 * #ROUND_HALF_EVEN
111 * #ROUND_UNNECESSARY
112 */
113 //求平均,并且保留小数
114 public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(ToBigDecimalFunction<? super T> mapper, int newScale, int roundingMode) {
115 return new CollectorImpl<>(
116 () -> new BigDecimal[]{new BigDecimal(0),new BigDecimal(0)},
117 (a, t) -> { a[0] = a[0].add(mapper.applyAsBigDecimal(t)); a[1] = a[1].add(BigDecimal.ONE); },
118 (a, b) -> { a[0] = a[0].add(b[0]) ; return a; },
119 a -> a[0].divide(a[1],MathContext.DECIMAL32).setScale(newScale,roundingMode), CH_NOID);
120 }
121 }
那么针对BigDecimal类型的求平均值可以写成如下:
1 Map<Integer, BigDecimal> result1 = list.stream().collect(Collectors.groupingBy(TestDTO::getId, CustomCollectors.averagingBigDecimal(TestDTO::getValue, 2, ROUND_DOWN)));