Here's an aside. If you want to see the differences between different versions of JDK and which API s have been added or deleted, you can view it through the following link:
The two versions in the path are the two versions to be compared. The interface is as follows:
At the same time, we can also find expired and obsolete API s and corresponding replacements through the built-in jdeps tool in JDK
jdeps --jdk-internals -R --class-path 'libs/*' $project
libs is the directory of all your dependencies, $project is the jar package of your project, and the sample output is as follows:
... JDK Internal API Suggested Replacement ---------------- --------------------- sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8 sun.reflect.Reflection Use java.lang.StackWalker @since 9
There are two updates to the Stream API in Java 16:
mapMulti and toList API s are added.
mapMulti
mapMulti is actually a supplement to the existing flatMap that is not suitable for use in some scenarios. flatMap is to continue the Stream after mapping an object to multiple objects. For example, take out each number in list < list < integer > > and convert it into a new list < integer >:
integerLists.stream().flatMap(integers -> integers.stream()).collect(Collectors.toList());
This is useful for scenarios where each element is itself a collection type. Let's take another example. Suppose there is an email Record class, including id, email sent to and email copied to:
record Mail(int id, Set<String> sendTo, Set<String> cc) {}
We want to find all the different contacts of a batch of emails, and finally put them into a List. It may be written as follows:
Set<String> collect = mails.stream().flatMap(mail -> { Set<String> result = new HashSet<>(); result.addAll(mail.sendTo()); result.addAll(mail.cc()); return result.stream(); }).collect(Collectors.toSet());
However, it is obviously not elegant to write in this way. First, an additional Set and corresponding Stream are created for each mail, and the sendTo and cc of each mail are traversed twice (addAll once, and the subsequent Stream again). In fact, we only take cc and sendTo out of the mail to participate in the subsequent Stream. In this scenario, mapMulti is very suitable:
Set<String> collect = mails.stream().<String>mapMulti((mail, consumer) -> { mail.cc().forEach(consumer::accept); mail.sendTo().forEach(consumer::accept); }).collect(Collectors.toSet());
It can be seen that:
- The input parameter of mapMulti is a BiConsumer, which actually uses the consumer in its parameter to receive the subsequent objects participating in the Stream
- The idea of mapMulti is to pass the object in the parameter that needs to participate in the subsequent Stream into the consumer to continue the Stream
- consumer does not restrict the object type. If you want to restrict, you must add the formal parameter < string >, otherwise set < Object > is returned instead of set < string >
Assuming that sendTo and cc of mail need to be obtained from other places, mapMulti can also realize:
Set<String> collect = mailIds.stream().<String>mapMulti((mailId, consumer) -> { mailService.getCCById(mailId).forEach(consumer::accept); mailService.getSendToById(mailId).forEach(consumer::accept); }).collect(Collectors.toSet());
There are also some interesting uses, such as converting a mixed type List to a unified type:
class C { static void expandIterable(Object e, Consumer<Object> c) { if (e instanceof Iterable<?> elements) { for (Object ie : elements) { expandIterable(ie, c); } } else if (e != null) { c.accept(e); } } public static void main(String[] args) { var nestedList = List.of(1, List.of(2, List.of(3, 4)), 5); Stream<Object> expandedStream = nestedList.stream().mapMulti(C::expandIterable); } }
Flexible use of optional Ifpresent (consumer <? Super T > action) method:
Stream.of(Optional.of("0"), Optional.of("1"), Optional.empty()) .mapMulti(Optional::ifPresent) .forEach(System.out::print);
toList
For Stream, toList is added to convert directly to List. Since the truncation operation in collect is not involved, it occupies less memory and requires less and faster operations than collect.
Before converting to List, you need to collect(Collectors.toList()), and the generated List is ArrayList, which is variable
However, the newly added Api, toList, generates an unmodifiable list, which is immutable.
Therefore, the two API s cannot be directly replaced with each other. You need to check and confirm that there is no change before replacing.
WeChat search "my programming meow" attention to the official account, daily brush, easy to upgrade technology, and capture all kinds of offer: