Unlock Java 9‑16: New APIs, Immutable Collections, and Stream Enhancements

This article introduces Java 9‑16 features such as factory methods for immutable collections, Optional.ifPresentOrElse, new Stream operations like takeWhile/dropWhile and toList, plus enhanced Duration and LocalDate utilities, providing concise, modern code patterns for developers.

21CTO
21CTO
21CTO
Unlock Java 9‑16: New APIs, Immutable Collections, and Stream Enhancements

People often stick to long‑tested Java 7/8, but this article introduces useful new APIs from Java 9‑13.

Java 9 added factory methods for immutable collections:

List.of(E... elements)

Set.of(E... elements)

Map.ofEntries(Entry<? extends K, ? extends V>... entries)

Previously you had to create a mutable list and wrap it with Collections.unmodifiableList:

List<String> list = new ArrayList<>();
list.add("abc");
list.add("xyz");
Collections.unmodifiableList(list);

Now you can do it in one line:

List.of("abc","xyz");

Java 9 also introduced Optional.ifPresentOrElse to reduce boilerplate:

Optional<Email> mail = ...;
if (mail.isPresent()) {
    send(mail.get());
} else {
    reportError();
}

It can be rewritten more flexibly:

mail.ifPresentOrElse(
    m -> send(m),
    () -> reportError()
);

Further improvement with Optional.or:

Optional<String> optional = Optional.<String>ofNullable("first")
    .or(() -> Optional.of("second"));

Optional can produce a Stream directly:

Optional.of(obj).stream();

Compared to the older pattern:

Optional.of(obj).map(Stream::of).orElse(Stream.empty());

Stream interface gained new methods in later versions:

default Stream<T> takeWhile(Predicate<? super T> predicate)
default Stream<T> dropWhile(Predicate<? super T> predicate)

These allow predicate‑based limiting or skipping of elements.

Example using IntStream.iterate with a predicate:

IntStream.iterate(1, i -> i < 16, i -> i + 1)
    .forEach(System.out::println);

Equivalent to the older two‑step approach:

IntStream.iterate(1, i -> i + 1)
    .takeWhile(i -> i < 16)
    .forEach(System.out::println);

Java 16 introduced Stream.toList() which is more convenient and performant than collect(Collectors.toList()):

collection.stream()
    .toList();

Java.time got more utilities; Duration can now provide parts directly:

Duration dur = Duration.between(now().minusDays(10).minusSeconds(567), now());
System.out.println(dur.toDaysPart());   // 10
System.out.println(dur.toMinutesPart()); // 9

Duration also supports division and creation with ChronoUnit:

Duration dur = Duration.of(3, ChronoUnit.HOURS);
Duration ans = dur.dividedBy(Duration.of(20, ChronoUnit.MINUTES));
System.out.println(ans); // 9

LocalDate now has datesUntil to produce a stream of dates between two dates:

Stream<LocalDate> dates = LocalDate.of(2021,3,3)
    .datesUntil(LocalDate.of(2021,10,9));
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaOptionalStream APIJava 9Immutable CollectionsJava 16Duration
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.