如何让同事看不懂你写的代码 然后觉得你非常牛逼 这里用到了stream()与Lambda 需要有点基础,没基础你炫个🔨
一. 需求
有一组(K=V)类型的字符串,需要你将它按照key分组并找到每组最大的数字收集起来,key需要经过排序(升序或者降序)
List<String> numStr = Lists.newArrayList("aa=1", "bb=10", "cc=1111", "aa=66","cc=22","dd=101");
二. 整活
一般思路 我们遍历整个list去将key与val分离出来然后set到map中去拿到最大val,然后使用treemap收集即可
这样的代码同事很容易看懂,并且代码又臭又长 这个时候需要借助我们的Lambda流式处理!
目标对象类
@Data
@Builder
static class NumObj{
private String key;
private Integer value;
}
直接上代码
System.out.println("map8: get sorted max element");
List<String> numStr = Lists.newArrayList("aa=1", "bb=10", "cc=1111", "aa=66","cc=22","dd=101");
Map<String, Integer> collect8 = numStr.stream().map(e -> {
String[] split = e.split("=");
return NumObj.builder().key(split[0]).value(Integer.parseInt(split[1])).build(); //老样子先转换成对象
}).collect(Collectors.groupingBy(NumObj::getKey // 然后通过groupingBy使用对象的KEY去分类 reducing(a,b,c)规约函数流由一个个元素组成,归约就是将一个个元素“折叠”成一个值,如求和、求最值、求平均值都是归约操作。
, Collectors.collectingAndThen(Collectors.reducing(0, NumObj::getValue, (c1, c2) -> { //collectingAndThen(a,b) 包装一层,不然外边拿到的是Optional类对象,
return c1>c2?c1:c2;
}), e -> e)));
collect8.forEach((k,v)->{
System.out.println(k+":"+v);
});
1. 首先先通过map将list的string转换为对象来操作
2. 再通过collect()函数来进行对流处理收集
3. groupingBy(a,b)函数进行具体收集处理 a为按照对象的哪个key进行分类,b为downstream代表具体怎么做处理
4. 由于我们是取最大值,那么我们可以使用规约函数reducing(a,b,c)来进行处理流由一个个元素组成,归约就是将一个个元素“折叠”成一个值,如求和、求最值、求平均值都是归约操作,a表示归约的初始值我们比大小值肯定存在,所以初始值设置为0,b表示需要进行归约操作的字段,c参数表示归约的过程,接收一个Lambda表达式,拥有两个参数,分别表示当前相邻的两个元素,我们需要比大小所以直接相比较即可
5. collectingAndThen(a,b) 通过这个函数来将规约处理拿到的Optional类转换为值,因为当我们使用groupingby分组时,值为空的肯定不会添加的Map中,我们可以放心大胆的拿
最终结果如上,代码看起来很整齐~
另一种写法
System.out.println("map9: get another sorted max element");
Map<String, Integer> collect9 = numStr.stream().map(e -> {
String[] split = e.split("=");
return NumObj.builder().key(split[0]).value(Integer.parseInt(split[1])).build();
}).collect(Collectors.groupingBy(NumObj::getKey,TreeMap::new,Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(NumObj::getValue)), e -> e.get().getValue())));
collect9.forEach((k,v)->{
System.out.println(k+":"+v);
});
1. Collectors.maxBy(Comparator.comparingInt(NumObj::getValue)直接通过maxBy函数拿到最大值
2. groupingby(a,b,c)也有三个参数方法,b代表收集的具体类实现,假如你想让key在map里面变得有序,可以传入Treemap::new 默认升序,也可以降序使用(() -> new TreeMap().descendingMap())替换Treemap::new