stream流去除对象的值_Java8Stream流使⽤及其基本原理Stream流,是对集合对象操作的增强
基本使⽤
⽐如有⼀个Person类的集合:List personList,可以通过stream()对集合中的元素进⾏操作,
下⾯的操作流程可以归纳为 过滤-映射-收集。
List personIdList = personList.stream()
//选出年龄⼤于20的Person对象
.filter(person -> Age() > 20)
//将Person对象映射成为它的属性id
.map(Person::getId)
//收集为List集合java stream
.List());
上述代码获取到了,年龄⼤于20岁的⼈id集合。
在 过滤-映射-收集 这个流程中:
过滤和映射属于中间操作,当操作结束时才会触发计算,可以⾼效地迭代⼤集合
收集属于结束操作,触发计算。
中间操作和结束操作
流操作可以分为 中间操作(惰性求值) 和 结束操作
中间操作指,操作过程中只记录操作⽽不做执⾏,直到执⾏结束操作,才会触发实际的操作,即惰性求值。
中间操作⼜分为:
⽆状态操作,元素处理不受之前元素影响,⽐如map()、filter()、skip()、peek()等
有状态操作,需要拿到所有元素才能进⾏,⽐如sorted()、limit()、distinct()等
结束操作是指,拿到所有元素后才能进⾏的操作。
结束操作⼜分为:
短路操作,遇到符合条件的元素后就可以终⽌,⽐如anyMatch()、findFirst()、findAny()等
⾮短路操作,需要处理所有元素,⽐如forEach()、collect()、max()、count()等。
例⼦
1.将List映射成⼀个Map,key为Person的id属性,value为Person实体类
Map PersonMap= personList.stream()
.Map(Person::getId, person -> person));
2.得到⼀个Map>集合,key为Person的age属性,value是按年龄分组后的Person对象集合:
Map> personsMap = personList.stream()
.upingBy(Person::getAge));
3.统计所有⼈年龄的总和:
int personAgeSum = personList.stream()
//根据age属性转换成IntStream
.mapToInt(Person::getAge)
.sum();
4.选出List集合中创建时间最晚的数据(createtime属性为Date类型)
UserInfo userInfoMax = userInfos.stream()
.max(Comparatorparing(UserInfo::getCreateTime))
.get();
这⾥的max⽅法实际返回的是Optional对象该对象可以通过orElse()⽅法设置对象UserInfo为null时的值:
UserInfo userInfoMax = userInfos.stream().max(Comparatorparing(UserInfo::getCreateTime))
.orElse(为null时的值); //这⾥如果max返回的对象为null(⼀般情况不会是),会取orElse()中的值
5.将所有⼩写字母拼接起来
String concat = Stream.of("a", "B", "c", "D", "e", "F")
.filter(x -> xpareTo("Z") > 0)
.reduce("", String::concat);
reduce⽅法的第⼀个参数是起始值,第⼆个参数是流中的元素,迭代流中的数据
也可以只传⼀个参数,即不指定起始值,这样会返回⼀个Optional对象
String concat = Stream.of("a", "B", "c", "D", "e", "F") .filter(x -> xpareTo("Z") > 0) .reduce(String::concat) .orElse("");
6.迭代map
使⽤foreach迭代map:albumsByArtist是⼀个map集合
Map countOfAlbums = new HashMap<>();
albumsByArtist.forEach((artist, albums) ->{
countOfAlbums.put(artist, albums.size());
});
7.使⽤map缓存
computeIfAbsent()⽅法接受⼀个 Lambda 表达式,当值不存在时使⽤ Lambda 表达式计算新值
Map artistCache = new HashMap<>();
根据key值name从artistCache获取对应的value,如果没有则调⽤readArtistFromDB⽅法获取值
publicArtist getArtist(String name) {return artistCacheputeIfAbsent(name, this::readArtistFromDB);
}
性能及基本原理简述
Stream 顾名思义,相当于批量处理数据的流⽔线。
在处理⼀般的数据量下,使⽤循环⽅式处理集合和通过stream⽅式处理集合的性能相差不⼤,但在数据⾥更⼤逻辑更复杂的情况下stream 要更优。
⽽parallelStream并⾏流,利⽤多核处理器的优势,并⾏(同⼀时间发⽣)处理数据(这意味着所处理的数据,不应该和顺序相关,否则会因为并⾏得到错误的结果),能够显著的提⾼执⾏速度。
Java8函数式编程书中提到,影响并⾏流的因素包括:
1.数据⼤⼩,并⾏化处理会带来额外的开销,只有每个数据处理管道花费的时间⾜够多时才有意义
2.数据结构,分割数据源,即把原有集合分成若⼲个集合到管道中
3.装箱,处理基本类型要⽐处理装箱类型快,装箱类型可以使⽤mapToInt等⽅法
4.处理器核的数量
5.单元处理开销:处理单个元素的花费时间越长,并⾏操作带来的性能提升越明显
Stream处理过程简述:
⾸先将Collection转化为Stream,流上的每个结点都只会返回包含上⼀结点引⽤的中间结点,使结点们
组成了⼀个双向链表结构,⽽不会⽴即进⾏任何数据处理。
每个中间操作都实现了Sink接⼝,实现了 makeSink() ⽅法⽤来返回⾃⼰的 Sink 实例,
只有当终⽌操作出现时,才开始将 Sink 实例化执⾏数据处理,
⽆状态操作的 Sink 接收到数据,会⽴即通知下游,有状态操作的 Sink 则会等要处理的数据处理完了才开始通知下游,
终⽌节点将数据收集起来后就完成了这次操作。
参考⽂章:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论