Explore Java 17’s New Time Formatting, Stream toList, mapMulti, and HexFormat
This article walks through Java 17’s lesser‑known enhancements—including the “B” pattern for time‑of‑day formatting, the concise Stream.toList() method, the versatile mapMulti() operation with practical examples, and the new HexFormat utility for hex conversions—while highlighting related bug fixes and usage tips.
1. Introduction
Besides the well‑known JEPs, Java 17 includes many other features. First, verify your Java version:
$ java --version
openjdk 17 2021-09-14
OpenJDK Runtime Environment (build 17+35-2724)
OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)Now let’s explore these treasures.
2. New Feature (JDK 16): “B” pattern for java.time formatting
The “B” pattern represents a time‑of‑day period such as “morning”, “afternoon”, or “evening”. It is added to DateTimeFormatter and DateTimeFormatterBuilder with built‑in internationalization support.
String format = DateTimeFormatter.ofPattern("B").format(LocalTime.now());
System.out.println(format); // 上午3. New Feature (JDK 16): Stream.toList() method
Since Java 8 introduced the Stream API, converting a list often required verbose code. The new toList() method shortens the pipeline:
numbers.stream().map(Integer::valueOf).toList();Two important points: Stream.toList() returns an unmodifiable list and does not accept null values, throwing a NullPointerException.
It is not a shorthand for collect(toUnmodifiableList()); it bypasses the Collector contract and uses less memory when the stream size is known.
4. New Feature (JDK 16): Stream.mapMulti() method
The mapMulti() default method is added to the Stream interface, with specialized versions for int, long, and double. It replaces each element with zero or more elements by invoking the provided mapper multiple times.
4.1 Zero‑to‑one mapping
Using mapMulti() you can filter and transform elements in a single pipeline:
Stream.of("Java","Valhalla","Panama","Loom","Amber")
.mapMulti((str, mapper) -> {
if (str.length() >= 5) mapper.accept(str.length());
})
.forEach(i -> System.out.print(i + " ")); // 8 6 54.2 One‑to‑one mapping
When each element maps to exactly one result, mapMulti() behaves like map():
Stream.of("Java","Valhalla","Panama","Loom","Amber")
.mapMulti((str, mapper) -> mapper.accept(str.length()))
.forEach(i -> System.out.print(i + " ")); // 4 8 6 4 54.3 One‑to‑many mapping
The mapper can be called multiple times per element, enabling transformations such as expanding a string into repeated characters:
Stream.of("Java","Valhalla","Panama","Loom","Amber","")
.mapMulti((str, mapper) -> {
for (int i = 0; i < str.length(); i++) {
mapper.accept(str.length());
}
mapper.accept(" ");
})
.forEach(System.out::print); // 4444 88888888 666666 4444 55555When to prefer mapMulti() over flatMap() ? mapMulti() allows the mapper to emit zero or many elements without creating intermediate stream objects, leading to better performance in scenarios with few output elements per input or when an imperative approach is simpler.
5. Bug Fix (JDK 16): Path.of / Paths.get null‑first‑argument check
Both methods now consistently throw NullPointerException when the first argument is null:
Path path = Path.of(null, "path/to/file");
// Exception java.lang.NullPointerException6. New Feature (JDK 17): java.util.HexFormat
The immutable, thread‑safe HexFormat class converts between bytes, chars, and hex strings, supporting custom prefixes, suffixes, and delimiters. Equality should be checked with equals().
// Default format
HexFormat hex = HexFormat.of();
byte b = 127;
String byteStr = hex.toHexDigits(b); // "7f"
byte digits = (byte) HexFormat.fromHexDigits(byteStr); // 127
// Custom format
HexFormat format = HexFormat.of()
.withPrefix("mica")
.withDelimiter(" ")
.withSuffix("微服务")
.withUpperCase();
String hexStr = format.formatHex("123".getBytes());
// mica31微服务 mica32微服务 mica33微服务
byte[] hexBytes = format.parseHex(hexStr);
System.out.println(new String(hexBytes)); // "123"7. Conclusion
The series has already published several Java 17 articles, with more in preparation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
