Java 8 Custom Collector

In this Article , we’ll Discuss How we can Create our own Custom Collector in java 8 and above.
For this article, We will implement Summary Statistics For BigDecimal number.

Java 8 Summary Statistics

Java 8 Provides Summary Statistics for Long,Int & Double. These Summary classes will help you to get count, min, max, sum, and average values.

  • LongSummaryStatistics
  • IntSummaryStatistics
  • DoubleSummaryStatistics
IntSummaryStatistics Example

In below example we are trying to calculate count, min, max, sum, and average of 1 to 100 Integer.

Calculate Sum,Min,Max,Count & Average
1
2
3
4
5

IntSummaryStatistics summaryStatistics = IntStream.range(1, 101)
.summaryStatistics();
System.out.println(summaryStatistics);

implementing SummaryStatistics for Big Decimal numbers

Java does not provides inbuilt Summary Statistics class for BigDecimal Number.

Lets try to implement our own BigDecimal SummaryStatistics.

Step 1 : Create Collector

Calculate Sum,Min,Max,Count & Average
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112


import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.stream.Collector;

public class MyBigDecimalSummaryCollector implements Consumer<BigDecimal> {

public static final int ROUND_HALF_UP = BigDecimal.ROUND_HALF_UP;

public static final Integer TRANSACTIONS_SCALE = 2;

private BigDecimal sum = BigDecimal.ZERO.setScale(TRANSACTIONS_SCALE, ROUND_HALF_UP);
private BigDecimal minimum = BigDecimal.ZERO.setScale(TRANSACTIONS_SCALE, ROUND_HALF_UP);
private BigDecimal maximum = BigDecimal.ZERO.setScale(TRANSACTIONS_SCALE, ROUND_HALF_UP);
private int count;

public static Collector<BigDecimal, ?, MyBigDecimalSummaryCollector> myBigDecimalSummaryStatistics() {

return Collector.of(MyBigDecimalSummaryCollector::new, MyBigDecimalSummaryCollector::accept,
MyBigDecimalSummaryCollector::merge);
}

@Override
public void accept(BigDecimal t) {

if (count == 0) {
firstElementSetup(t);
} else {
sum = sum.add(t);
minimum = minimum.min(t);
maximum = maximum.max(t);
count++;
}
}

public MyBigDecimalSummaryCollector merge(MyBigDecimalSummaryCollector s) {
if (s.count > 0) {
if (count == 0) {
setupFirstElement(s);
} else {
sum = sum.add(s.sum);
minimum = minimum.min(s.minimum);
maximum = maximum.max(s.maximum);
count += s.count;
}
}
return this;
}

private void setupFirstElement(MyBigDecimalSummaryCollector s) {
count = s.count;
sum = s.sum;
minimum = s.minimum;
maximum = s.maximum;
}

private void firstElementSetup(BigDecimal t) {
count = 1;
sum = t;
minimum = t;
maximum = t;
}

public BigDecimal getAverage() {
if (count == 0) {
return BigDecimal.ZERO.setScale(TRANSACTIONS_SCALE, ROUND_HALF_UP);
}
return sum.divide(BigDecimal.valueOf(count), TRANSACTIONS_SCALE,
ROUND_HALF_UP);

}

public BigDecimal getSum() {
return sum;
}

public void setSum(BigDecimal sum) {
this.sum = sum;
}

public BigDecimal getMinimum() {
return minimum;
}

public void setMinimum(BigDecimal minimum) {
this.minimum = minimum;
}

public BigDecimal getMaximum() {
return maximum;
}

public void setMaximum(BigDecimal maximum) {
this.maximum = maximum;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

@Override
public String toString() {
return "MyBigDecimalSummaryCollector [sum=" + sum + ", minimum=" + minimum + ", maximum=" + maximum + ", count="
+ count + "]";
}
}

Step 2 :

Use Collector
1
2
3
4
5
6
7

MyBigDecimalSummaryCollector collect = IntStream.range(1, 101)
.mapToObj(number -> BigDecimal.valueOf(number))
.collect(MyBigDecimalSummaryCollector.myBigDecimalSummaryStatistics());

System.out.println(collect);

Share Comments