Table of Contents
1. Compact Strings (Java 9+)
What Changed?
Prior to Java 9, Strings used a char[]
(2 bytes per character). Compact Strings optimize memory by:
- Using
byte[]
with Latin-1 (1 byte per character) for strings with ISO-8859-1 characters. - Falling back to UTF-16 (2 bytes) for extended Unicode (e.g., emojis, Asian scripts).
Impact
- Memory Savings: Up to 50% reduction for ASCII-heavy apps.
- Backward Compatibility: No code changes needed – handled internally.
Disabling Compact Strings (Rarely needed):
java -XX:-CompactStrings MyApp
2. String Interning with intern()
How Interning Works
The intern()
method adds a String to the String Pool (or returns an existing pooled instance):
String s1 = new String("Java").intern();
String s2 = "Java";
System.out.println(s1 == s2); // true
Use Cases
- Deduplicate Repeated Strings (e.g., parsing CSV with repeated values).
- Optimize Memory in legacy apps with limited heap.
Pitfalls
- Overuse: Can bloat the String Pool, causing PermGen/metaspace issues.
- Performance:
intern()
is costly; benchmark before using in hot code paths.
3. Custom String-Backed Data Structures
Example: Trie for Autocomplete
Build a prefix tree for efficient word lookups:
class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
boolean isWord;
}
class Trie {
TrieNode root = new TrieNode();
void insert(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
node = node.children.computeIfAbsent(c, k -> new TrieNode());
}
node.isWord = true;
}
boolean search(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
node = node.children.get(c);
if (node == null) return false;
}
return node.isWord;
}
}
Usage:
Trie trie = new Trie();
trie.insert("apple");
System.out.println(trie.search("apple")); // true
System.out.println(trie.search("app")); // false not a full-word
trie.insert("app");
System.out.println(trie.search("app")); // true
Example Summary:
- The
Trie
supports efficient insertion (insert
) and search (search
) operations. - Searching for words has a time complexity of O(n), where n is the word length.
- It is useful in applications like autocomplete, dictionary search, and spell checking.
4. Niche Methods & Techniques
Java 15+: formatted()
Alternative to String.format()
:
String template = "User: %s | Age: %d";
String result = template.formatted("Alice", 30);
Java 12+: transform()
Chain string transformations:
String text = " Hello, World! ";
String cleaned = text
.transform(String::strip)
.transform(s -> s.replace(",", ""))
.transform(String::toLowerCase); // "hello world!"
Java 12+: indent()
Adjust string indentation dynamically:
String code = "public class Main {\nvoid run() {}\n}";
System.out.println(code.indent(4)); // Adds 4 spaces per line
Best Practices
- Avoid Premature Optimization: Use Compact Strings and interning only after profiling.
- Prefer Libraries for Data Structures: Use Apache Commons or Guava for production-grade tries.
- Leverage New Methods:
transform()
/indent()
improve readability in modern codebases.
FAQ
Does intern()
improve performance in all cases?
No – it can degrade performance due to pool contention. Use only for proven memory issues.
Are Compact Strings enabled by default?
Yes, in Java 9+. No action needed to benefit.
When to use a custom trie vs HashSet<String>
?
Tries excel at prefix searches (autocomplete). For exact matches, use HashSet
.