Java 21 API Additions: StringBuilder.repeat, Math.clamp
Introduction
Alongside virtual threads and pattern matching, Java 21Click to read tutorial: Overview of New Features in Java 21 added a set of small methods to the core libraries which make everyday code shorter. This tutorial explains the Java 21 API additions with examples -
OUTPUT of the above code
Math.clamp()
Keeping a value within a range is a very common operation - a percentage between 0 and 100, a page number between 1 and the last page. It used to be written as
OUTPUT of the above code
There are versions for
OUTPUT of the above code
Note the difference: digits are technically emoji characters (they combine into keycap emoji), so
A closeable HttpClient and the KEM API
The Java 11 HTTP ClientClick to read: Java 11 HTTP Client now implements
OUTPUT of the above code
The shared secret key is then used with a symmetric cipher such as AES-GCM to encrypt the actual data.
Other additions
Java 21 also added
StringBuilder.repeat(), String.indexOf() with a range and splitWithDelimiters(), Math.clamp(), Character methods for emoji, an HttpClient which can be closed, and the new Key Encapsulation Mechanism API. Every example is compiled for Java 21.
StringBuilder.repeat() and new String methods
StringBuilder.repeat, indexOf with a range, splitWithDelimiters
//StringAdditions.java
import java.util.Arrays;
public class StringAdditions {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append('+').repeat("-", 10).append('+').append('\n'); // repeat a CharSequence
sb.append('|').repeat(' ', 10).append("|\n"); // repeat a character (code point)
sb.append('+').repeat("-", 10).append('+');
System.out.println(sb);
String path = "/usr/local/lib/java";
int slash = path.indexOf('/', 1, 10); // search only between index 1 and 10
System.out.println("First '/' between 1 and 10: " + slash);
String expr = "12+3*4-5";
System.out.println(Arrays.toString(expr.split("[+*-]"))); // delimiters lost
System.out.println(Arrays.toString(expr.splitWithDelimiters("[+*-]", 0))); // delimiters kept
}
}
+----------+ | | +----------+ First '/' between 1 and 10: 4 [12, 3, 4, 5] [12, +, 3, *, 4, -, 5]
StringBuilder.repeat()(and the same method onStringBuffer) appends a string or a character several times, complementingString.repeat()from Java 11, without creating an intermediate string.indexOf(ch, beginIndex, endIndex)searches only within a range - here it finds the second slash, at index 4, and would ignore any after index 10.splitWithDelimiters()splits likesplit()but keeps the matched delimiters as separate elements, which is exactly what a simple tokenizer for an arithmetic expression needs.
Math.min(Math.max(value, min), max), which is easy to get backwards. Java 21 added Math.clamp() -
Clamping values to a range
//ClampDemo.java
public class ClampDemo {
public static void main(String[] args) {
for (int value : new int[] {-20, 45, 130}) {
System.out.println(value + " -> " + Math.clamp(value, 0, 100));
}
long bigPage = 5_000_000_000L;
int page = Math.clamp(bigPage, 1, 250); // clamp a long into an int range: returns int
System.out.println("Page: " + page);
System.out.println("Opacity: " + Math.clamp(1.7, 0.0, 1.0));
try {
Math.clamp(5, 10, 1); // min greater than max
} catch (IllegalArgumentException e) {
System.out.println("Bad range: " + e.getMessage());
}
}
}
-20 -> 0 45 -> 45 130 -> 100 Page: 250 Opacity: 1.0 Bad range: 10 > 1
int, long, float and double. The version taking a long value with int bounds returns an int, so it doubles as a safe narrowing conversion.
Emoji in Character
Java 21 added methods to Character which test the Unicode emoji properties of a code point, such as isEmoji(), isEmojiPresentation() and isExtendedPictographic() - useful for counting, filtering or validating user text -
Finding emoji in text
//EmojiDemo.java
public class EmojiDemo {
public static void main(String[] args) {
String message = "Java 21 is here 🚀 enjoy ☕"; // rocket and hot beverage
long emojiCount = message.codePoints().filter(Character::isEmojiPresentation).count();
System.out.println("Emoji found: " + emojiCount);
message.codePoints().filter(Character::isEmojiPresentation)
.forEach(cp -> System.out.println(" U+" + Integer.toHexString(cp).toUpperCase()));
System.out.println("Is the digit '2' an emoji? " + Character.isEmoji('2')
+ ", shown as emoji by default? " + Character.isEmojiPresentation('2'));
}
}
Emoji found: 2 U+1F680 U+2615 Is the digit '2' an emoji? true, shown as emoji by default? false
isEmoji('2') is true, but they are not displayed as emoji by default, which isEmojiPresentation() reports.
AutoCloseable, so its threads and connections can be released explicitly, in a try-with-resources block. And Java 21 (JEP 452) added javax.crypto.KEM, an API for key encapsulation mechanisms: a sender uses the receiver's public key to generate a fresh secret key plus an "encapsulation" of it, and only the receiver's private key can recover the same secret key from the encapsulation. KEMs are the building block of modern protocols such as TLS 1.3 and HPKE, and of the quantum-resistant ML-KEMClick to read: quantum-resistant ML-KEM added in Java 24 -
Sharing a secret key with DHKEM
//KemDemo.java
import java.net.http.HttpClient;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Arrays;
import javax.crypto.KEM;
import javax.crypto.SecretKey;
public class KemDemo {
public static void main(String[] args) throws Exception {
try (HttpClient client = HttpClient.newHttpClient()) { // closed automatically (Java 21)
System.out.println("HttpClient created and closed");
}
KeyPair receiver = KeyPairGenerator.getInstance("X25519").generateKeyPair();
KEM kem = KEM.getInstance("DHKEM");
KEM.Encapsulator sender = kem.newEncapsulator(receiver.getPublic());
KEM.Encapsulated result = sender.encapsulate(); // a new secret + its encapsulation
SecretKey senderKey = result.key();
byte[] encapsulation = result.encapsulation(); // sent to the receiver
KEM.Decapsulator decapsulator = kem.newDecapsulator(receiver.getPrivate());
SecretKey receiverKey = decapsulator.decapsulate(encapsulation);
System.out.println("Encapsulation size: " + encapsulation.length + " bytes");
System.out.println("Both sides have the same key: " + Arrays.equals(senderKey.getEncoded(), receiverKey.getEncoded()));
}
}
HttpClient created and closed Encapsulation size: 32 bytes Both sides have the same key: true
Collections.shuffle(list, RandomGenerator), accepting any of the Java 17 random generatorsClick to read: Java 17 random generators, and the sequenced collectionsClick to read tutorial: Java 21 Sequenced Collections Explained methods.
Summary
In this tutorial we went through the library additions in Java 21. We built text with StringBuilder.repeat(), searched a range with indexOf(), tokenized with splitWithDelimiters(), kept values in range with Math.clamp(), and found emoji with the new Character methods. Lastly, we closed an HttpClient with try-with-resources, and shared a secret key with the new KEM API. To see everything new from Java 18 to 21 in one place, read the overview of new features in Java 21Click to read tutorial: Overview of New Features in Java 21.Continue Reading Java 18 to 21 Tutorials
Overview of New Features in Java 21Click to read tutorial: Overview of New Features in Java 21 Java 21 Virtual Threads Tutorial with ExamplesClick to read tutorial: Java 21 Virtual Threads Tutorial with Examples Java 21 Record Patterns with ExamplesClick to read tutorial: Java 21 Record Patterns with Examples Java 21 Pattern Matching for switch with ExamplesClick to read tutorial: Java 21 Pattern Matching for switch with Examples Java 21 Sequenced Collections ExplainedClick to read tutorial: Java 21 Sequenced Collections Explained Java 21 Generational ZGC ExplainedClick to read tutorial: Java 21 Generational ZGC Explained Overview of New Features in Java 18Click to read tutorial: Overview of New Features in Java 18 Overview of New Features in Java 19Click to read tutorial: Overview of New Features in Java 19 Overview of New Features in Java 20Click to read tutorial: Overview of New Features in Java 20
Overview of New Features in Java 21Click to read tutorial: Overview of New Features in Java 21 Java 21 Virtual Threads Tutorial with ExamplesClick to read tutorial: Java 21 Virtual Threads Tutorial with Examples Java 21 Record Patterns with ExamplesClick to read tutorial: Java 21 Record Patterns with Examples Java 21 Pattern Matching for switch with ExamplesClick to read tutorial: Java 21 Pattern Matching for switch with Examples Java 21 Sequenced Collections ExplainedClick to read tutorial: Java 21 Sequenced Collections Explained Java 21 Generational ZGC ExplainedClick to read tutorial: Java 21 Generational ZGC Explained Overview of New Features in Java 18Click to read tutorial: Overview of New Features in Java 18 Overview of New Features in Java 19Click to read tutorial: Overview of New Features in Java 19 Overview of New Features in Java 20Click to read tutorial: Overview of New Features in Java 20