Java8 Stream实战(三)

Java8 Stream实战(三)

前言

本想接着上一章 Java8 Stream实战(二) 继续往后开展 Java8 Stream 相关API实践,但是考虑到今天要介绍的内容不仅仅只是针对现有 API ,还有如何对 Stream#reduce 进行相关的拓展,以满足日常开发的需要,于是单独开一篇进行介绍。

开始

Reduce of BIgdecimal

注:Stream#reduce 有三个重载方法,本篇对此不多赘述,有兴趣可以查阅《Java 8 in Action》

为什么会有这篇章节呢?日常开发中我们会遇到如下场景

1
2
3
int sum = list.stream().mapToInt(XXXBean::getIntValue).sum();
int max = list.stream().mapToInt(XXXBean::getIntValue).max().orElse(0);
int min = list.stream().mapToInt(XXXBean::getIntValue).min().orElse(0);

sum()max()min() 函数是 java.util.stream.IntStream 像我们提供的,我们可以很方便的利用这些函数来完成求和、取最大值、取最小值等等操作。

可是有时候整形(如上述代码 int)不能满足我们一些对精度有着较高要求的场景,如金钱、重量等等。针对这些场景我们可能会使用BIgdecimal,这时候我们不得不使用 Stream#reduce 来自定义(如下面代码针对的BIgdecimalStream 收集行为,而本小节则是对一些常见场景的收集行为进行封装以达到复用的目的。

注:关于BIgdecimal 的封装工具类为 BigDecimals ,以下代码只包含方法部分代码

sum

1
2
3
4
public static BigDecimal sum(BigDecimal b1, BigDecimal b2) {
Assert.isTrue(b1 != null && b2 != null, "arguments of BigDecimals#sum is not allowed be null.");
return b1.add(b2);
}

max

1
2
3
4
public static BigDecimal max(BigDecimal b1, BigDecimal b2) {
Assert.isTrue(b1 != null && b2 != null, "arguments of BigDecimals#max is not allowed be null.");
return b1.compareTo(b2) > 0 ? b1 : b2;
}

min

1
2
3
4
public static BigDecimal min(BigDecimal b1, BigDecimal b2) {
Assert.isTrue(b1 != null && b2 != null, "arguments of BigDecimals#min is not allowed be null.");
return b1.compareTo(b2) < 0 ? b1 : b2;
}

为了方便测试,我们在BIgdecimals 中提供了生成集合的静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static List<Person> getPersons() {
Random random = new Random();
return Stream.generate(() -> random.nextInt(6)).limit(20).map(num -> {
Person person = new Person();
person.setId(num);
person.setUsername("name" + num);
person.setAccount(BigDecimal.valueOf(num));
return person;
}).collect(Collectors.toList());
}


@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Person {

private int id;

private String username;

private BigDecimal account;
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void customBigDecimalReduce() {

BigDecimal sum = Stream.iterate(BigDecimal.ZERO, n -> n.add(BigDecimal.ONE)).limit(20).reduce(BigDecimals::sum).orElse(BigDecimal.ZERO);
BigDecimal max = Stream.iterate(BigDecimal.ZERO, n -> n.add(BigDecimal.ONE)).limit(20).reduce(BigDecimals::max).orElse(BigDecimal.ZERO);
BigDecimal min = Stream.iterate(BigDecimal.ZERO, n -> n.add(BigDecimal.ONE)).limit(20).reduce(BigDecimals::min).orElse(BigDecimal.ZERO);

List<BigDecimals.Person> persons = BigDecimals.getPersons();
System.out.println("persons: " + persons);
Map<String, BigDecimal> complexSum = persons.stream()
.filter(person -> person.getId() != 0)
.collect(Collectors.toMap(BigDecimals.Person::getUsername, BigDecimals.Person::getAccount, BigDecimals::sum));

// print
System.out.println("sum: " + sum);
System.out.println("max: " + max);
System.out.println("min: " + min);
System.out.println("complexSum: " + complexSum);
}

因为生成测试集合的方法 BigDecimals#getPersons 存在随机性,如下结果仅代表本人电脑本次测试结果,如下:

1
2
3
4
5
persons: [BigDecimals.Person(id=0, username=name0, account=0), BigDecimals.Person(id=2, username=name2, account=2), BigDecimals.Person(id=5, username=name5, account=5), BigDecimals.Person(id=3, username=name3, account=3), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=5, username=name5, account=5), BigDecimals.Person(id=2, username=name2, account=2), BigDecimals.Person(id=2, username=name2, account=2), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=4, username=name4, account=4), BigDecimals.Person(id=1, username=name1, account=1), BigDecimals.Person(id=1, username=name1, account=1)]
sum: 190
max: 19
min: 0
complexSum: {name5=10, name4=24, name3=3, name2=6, name1=7}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×