What’s New in Java 21? Explore Updated String, Collections, and More
This article walks through the latest Java 21 additions—including enhanced String search methods, new Emoji utilities in Character, repeat() for StringBuilder and StringBuffer, updated Charset factories, named regex groups, SequencedCollection interfaces, localized DateTimeFormatter patterns, extended Math and BigInteger operations, and improved Thread and Future APIs—providing code examples and usage guidance.
Introduction
Besides the well‑known JEPs, Java 21 brings many other enhancements. First, verify your Java version:
<code>$ java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)
</code>We will review new APIs for String and its related classes such as Collections, Date, Time, HttpClient, concurrency utilities, Math, and BigInteger.
String (Java 21 additions)
String now includes overloaded
indexOf()methods that allow searching for a single character or substring within a specific start and end index.
<code>public int indexOf(int ch, int beginIndex, int endIndex);
public int indexOf(String str, int beginIndex, int endIndex);
</code>Example:
<code>String text = "JAVA架构日记-2023-如梦技术";
int index = text.indexOf("0", 5, 15);
</code>Character (Java 21 additions)
The Character class adds five methods to support Emoji handling:
<code>public static boolean isEmoji(int codePoint);
public static boolean isEmojiPresentation(int codePoint);
public static boolean isEmojiModifier(int codePoint);
public static boolean isEmojiModifierBase(int codePoint);
public static boolean isEmojiComponent(int codePoint);
public static boolean isExtendedPictographic(int codePoint);
</code>All these methods accept an
intcode point and determine whether it represents the corresponding Emoji property.
StringBuffer and StringBuilder (Java 21 additions)
Both
StringBufferand
StringBuildergain a
repeat()method for repeating a character or a CharSequence multiple times.
StringBuilder:
<code>@Override
public StringBuilder repeat(int codePoint, int count);
@Override
public StringBuilder repeat(CharSequence cs, int count);
</code>StringBuffer:
<code>@Override
public synchronized StringBuffer repeat(int codePoint, int count);
@Override
public synchronized StringBuffer repeat(CharSequence cs, int count);
</code>Charset (Java 18 addition)
Charset introduces a new
forName()method that accepts a fallback charset:
<code>public static Charset forName(String charsetName, Charset fallback);
</code>Regex Group Optimization (Java 20)
Named capturing groups are now accessible via
Matcher.namedGroups(). The address‑resolution example can be simplified:
<code>public static Map<String, String> getAddressResolution(String address) {
Matcher matcher = PATTERN.matcher(address);
Map<String, String> row = new HashMap<>();
if (matcher.matches()) {
Map<String, Integer> groupMap = matcher.namedGroups();
groupMap.forEach((key, group) -> row.put(key, matcher.group(group)));
}
return row;
}
</code>Collections (Java 21 additions)
Three new interfaces are added to the Collections framework:
SequencedCollection,
SequencedSet, and
SequencedMap.
<code>interface SequencedCollection<E> extends Collection<E> {
// new method
SequencedCollection<E> reversed();
// methods promoted from Deque
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
}
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
SequencedSet<E> reversed(); // covariant override
}
interface SequencedMap<K,V> extends Map<K,V> {
// new methods
SequencedMap<K,V> reversed();
SequencedSet<K> sequencedKeySet();
SequencedCollection<V> sequencedValues();
SequencedSet<Entry<K,V>> sequencedEntrySet();
V putFirst(K, V);
V putLast(K, V);
// methods promoted from NavigableMap
Entry<K,V> firstEntry();
Entry<K,V> lastEntry();
Entry<K,V> pollFirstEntry();
Entry<K,V> pollLastEntry();
}
</code>The class diagram changes accordingly:
Factory methods for creating maps with a given initial capacity are also added (Java 19):
<code>HashMap.newHashMap(100);
HashSet.newHashSet(100);
LinkedHashMap.newLinkedHashMap(100);
LinkedHashSet.newLinkedHashSet(100);
WeakHashMap.newWeakHashMap(100);
</code>Date and Time API (Java 19 additions)
DateTimeFormatter.ofLocalizedPattern()creates a localized formatter from a pattern string, and
DateTimeFormatterBuilder.appendLocalized()adds a localized pattern.
<code>LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedPattern("yM");
System.out.println(now.format(formatter)); // e.g., 2023年9月
</code>IO Streams (Java 18 addition)
PrintStreamnow provides a
charset()method to retrieve the charset in use:
<code>public Charset charset();
</code>Classes such as
HttpClient,
ExecutorService, and
ForkJoinPoolnow implement
AutoCloseable, allowing use with try‑with‑resources.
Math and BigInteger (Java 19 additions)
New methods in
Mathinclude ceiling division, exact division, ceiling/floor modulus, and
clamp()overloads for primitive types, as well as
unsignedMultiplyHigh()for unsigned long multiplication.
<code>public static int ceilDiv(int x, int y);
public static long ceilDiv(long x, int y);
public static long ceilDiv(long x, long y);
public static int ceilDivExact(int x, int y);
public static long ceilDivExact(long x, long y);
public static int ceilMod(int x, int y);
public static long ceilMod(long x, long y);
public static int divideExact(int x, int y);
public static long divideExact(long x, long y);
public static int floorDivExact(int x, int y);
public static long floorDivExact(long x, long y);
public static int clamp(long value, int min, int max);
public static long clamp(long value, long min, long max);
public static double clamp(double value, double min, double max);
public static float clamp(float value, float min, float max);
public static long unsignedMultiplyHigh(long x, long y);
</code> BigIntegergains
parallelMultiply(BigInteger val)to perform multiplication using the Fork/Join framework.
<code>public BigInteger parallelMultiply(BigInteger val);
</code>Thread (Java 21 additions)
Thread now includes
join(Duration),
sleep(Duration), and
isVirtual()methods, all accepting a
Durationargument.
<code>public static void sleep(Duration duration) throws InterruptedException;
public final boolean join(Duration duration) throws InterruptedException;
public final boolean isVirtual();
</code>Future (Java 21 additions)
Three new methods are added to the
Futureinterface:
resultNow()– returns the result without throwing checked exceptions.
exceptionNow()– returns the exception without checked‑exception handling.
state()– returns a
Future.Stateenum indicating the task’s current status.
<code>enum State {
/** Task not yet completed */
RUNNING,
/** Task completed successfully */
SUCCESS,
/** Task completed with an exception */
FAILED,
/** Task was cancelled */
CANCELLED
}
</code>These APIs enable more precise monitoring of asynchronous tasks.
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.