stream的实用方法和注意事项
作者:袁俊子(圆镜) 出品:大淘宝技术
相信大家一定都在项目开发中享受过stream带来的便利性和优雅的代码风格。接下来补充几个项目中不常见到但是同样实用的api,同时跟大家一起探讨stream这把双刃剑的另一面。
使用但不常见的方法
filter、map、skip等方法想必大家都十分熟悉 无需赘述。这里仅介绍工程中使用较少但同样实用的方法。
reduce
reduce有3个参数:初始值、累加器、组合器。下面通过几个case为大家逐一讲解。由于比较绕,下面贴上ide执行结果
当顺序读流或者累加器的参数和它的实现的类型匹配时,我们不需要使用组合器。通常只有在处理对象属性时则需要组合器来帮助编译器推断入参类型。实际在串行流中组合器并不会实际执行,只需要出入参类型满足编译器推断要求即可。可以看到上方result3的计算,末尾组合器适用max还是min 结果是一样的。
allMatch/anyMatch/noneMatch
判断集合中是否 全部都匹配/存在任意匹配/不存在匹配 某一规则。
比如下面一段代码,判断集合中的对象是否全部合法。语义十分简单。下面对比stream写法和常规写法。两种写法的运行结果是一样的。
@Data @AllArgsConstructor public static class Calendar { private LocalDate date; private boolean today; private boolean signed; } //日历初始化 LocalDate now = new LocalDate(); List<Calendar> calendars = Arrays.asList( new Calendar(new LocalDate(1661174238000L), false, false) , new Calendar(new LocalDate(1661828371000L), false, false) , new Calendar(new LocalDate(1661433438000L), false, false) , new Calendar(new LocalDate(1661519838000L), false, false) , new Calendar(new LocalDate(1661779038000L), false, false) , new Calendar(now, true, true) ); //判断昨天是否签到过。写法一 boolean yesterdaySigned = calendars.stream() .anyMatch( t -> Days.daysBetween(t.getDate(), now).getDays() == 1 && t.isSigned() ); System.out.println("昨天是否签到过 -> " + yesterdaySigned); //写法二 boolean yesterdaySigned2 = false; for (Calendar calendar : calendars) { if (Days.daysBetween(calendar.getDate(), now).getDays() == 1) { //找到昨天的日历,并判断是否签到 yesterdaySigned2 = calendar.isSigned(); break; } } System.out.println("昨天是否签到过写法二 -> " + yesterdaySigned2);
这里写法一虽然更简练但是存在问题,大家有看出来的吗。这个问题放在“注意事项”中专门讲解。
带你读《2022技术人的百宝黑皮书》——stream的实用方法和注意事项(2)https://developer.aliyun.com/article/1339661?groupCode=taobaotech