当前位置: 首页 > 后端技术 > Java

关于Java16中新的Stream接口的一些思考

时间:2023-04-01 14:47:31 Java

这里扯个题外话。如果想查看不同版本JDK的区别,新增或删除了哪些API,可以通过以下链接查看:https://javaalmanac.io/jdk/17...路径中的两个版本是要比较的两个版本。界面如下:同时我们也可以使用JDK自带的jdeps工具查找过时和废弃的API以及相应的替换jdeps--jdk-internals-R--class-path'libs/*'$projectlibs是你所有依赖的目录,$project是你的项目jar包,示例输出:...JDKInternalAPISuggestedReplacement------------------------------------sun.misc.BASE64Encoder使用java.util.Base64@since1.8sun.reflect.Reflection使用java.lang.StackWalker@since9Java16有两个更新StreamAPI:新增mapMulti和toList两个API。mapMultimapMulti其实主要是对现有的flatMap在某些场景下不适合使用的补充。flatMap是将一个对象映射成多个对象,然后继续流,比如取出List>中的每一个数,转换成一个新的List:integerLists.stream().flatMap(integers->integers.stream()).collect(Collectors.toList());这非常适合每个元素本身都是集合类型的场景。我们再看一个例子,假设有一个Record类的邮件,包括id,发送到的邮件,复制到的邮件:recordMail(intid,SetsendTo,Setcc){}我们要查找一批邮件的所有不同的联系人,最后把他们放到一个List中,可以这样写:Setcollect=mails.stream().flatMap(mail->{Setresult=newHashSet<>();result.addAll(mail.sendTo());result.addAll(mail.cc());returnresult.stream();}).collect(收集器.toSet());这是非常不雅的。首先为每一个Mail额外创建一个Set和对应的Stream,遍历每一个Mail的sendTo和cc两次(addAll一次,后面的Stream再次遍历)。其实我们目前只是把mail中的cc和sendTo取出来参与后续的Stream。这种场景下,非常适合使用mapMulti:Setcollect=mails.stream().ma??pMulti((mail,consumer)->{mail.cc().forEach(consumer::accept);mail.sendTo().forEach(consumer::accept);}).collect(Collectors.toSet());可以看出mapMulti的入参是一个BiConsumer,其实就是利用其参数中的consumer来接收并参与Stream后续对象mapMulti的思路是传递参数中需要的对象参与后续的Stream给consumer继续Streamconsumer。对象类型没有限制。如果要限制,必须加上形参,否则最终返回的是Set而不是Set假设邮件的sendTo和cc需要从其他地方获取,而它也可以使用mapMulti实现:Setcollect=mailIds.stream().ma??pMulti((mailId,consumer)->{mailService.getCCById(mailId).forEach(consumer::accept);getSendToById(mailId).forEach(consumer::accept);}).collect(Collectors.toSet());还有一些有趣的用法,比如将混合类型的List转换为统一类型:classC{staticvoidexpandIterable(Objecte,Consumerc){if(einstanceofIterableelements){for(对象即:元素){expandIterable(即c);}}elseif(e!=null){c.accept(e);}}publicstaticvoidmain(String[]args){varnestedList=List.of(1,List.of(2,List.of(3,4)),5);StreamexpandedStream=nestedList.stream().mapMulti(C::expandIterable);}}使用Optional.ifPresent(Consumeraction)方法:Stream.of(Optional.of("0"),Optional.of("1"),Optional.empty()).mapMulti(Optional::ifPresent).forEach(System.out::print);toList将toList添加到Stream中,并直接将其转换为List。由于不涉及collect中的截断操作,因此比collect占用内存少,操作少,速度快。转List之前,collect(Collectors.toList()isrequired),生成的List是ArrayList,是可变的,但是这次新增的Api,toList生成的是UnmodifiableList,是不可变的。所以这两个API不能直接互相替换,需要做一些检查确认没有变化再替换。微信搜索“我的编程喵”关注公众号,天天刷,轻松提升技能,赢各种优惠: