Fundamentals 13 min read

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.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
What’s New in Java 21? Explore Updated String, Collections, and More

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

int

code point and determine whether it represents the corresponding Emoji property.

StringBuffer and StringBuilder (Java 21 additions)

Both

StringBuffer

and

StringBuilder

gain 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)

PrintStream

now provides a

charset()

method to retrieve the charset in use:

<code>public Charset charset();
</code>

Classes such as

HttpClient

,

ExecutorService

, and

ForkJoinPool

now implement

AutoCloseable

, allowing use with try‑with‑resources.

Math and BigInteger (Java 19 additions)

New methods in

Math

include 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>
BigInteger

gains

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

Duration

argument.

<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

Future

interface:

resultNow()

– returns the result without throwing checked exceptions.

exceptionNow()

– returns the exception without checked‑exception handling.

state()

– returns a

Future.State

enum 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.

JavaConcurrencyAPIDateTimeCollectionsstringjava21
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login 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.