Keywords: Java value pair collections | generic Pair class | AbstractMap.SimpleEntry | record classes | type safety
Abstract: This article provides an in-depth exploration of value pair collection implementations in Java, focusing on the design and implementation of custom generic Pair classes, covering key features such as immutability, hash computation, and equality determination. It also compares Java standard library solutions like AbstractMap.SimpleEntry, Java 9+ Map.entry methods, third-party library options, and modern implementations using Java 16 records, offering comprehensive technical references for different Java versions and scenarios. Through detailed code examples and performance analysis, the article helps developers choose the most suitable value pair storage solutions.
Background of Value Pair Collection Requirements
In Java programming, there is often a need to handle collections of elements consisting of two values of different types. Unlike Maps, these collections do not require one value to serve as a unique key but need to maintain insertion order. For example, storing a series of string and integer pairs like <String, Integer>, where the string is not a unique identifier.
Core Implementation of Custom Pair Class
Based on the best answer from the Q&A data, we can design a type-safe, immutable generic Pair class. This implementation avoids the type casting issues associated with Object arrays while being more concise than creating full classes.
public class Pair<L, R> {
private final L left;
private final R right;
public Pair(L left, R right) {
assert left != null;
assert right != null;
this.left = left;
this.right = right;
}
public L getLeft() { return left; }
public R getRight() { return right; }
@Override
public int hashCode() {
return left.hashCode() ^ right.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) return false;
Pair pairo = (Pair) o;
return this.left.equals(pairo.getLeft()) &&
this.right.equals(pairo.getRight());
}
}
Key features of this implementation include: generic type parameters ensuring compile-time type safety; final fields guaranteeing immutability; overridden hashCode method using XOR operation for reasonable hash distribution; equals method performing strict value equality comparison.
Collection Operation Examples
Using the custom Pair class to create ordered collections:
List<Pair<String, Integer>> pairList = new ArrayList<>();
pairList.add(new Pair<>("Alice", 25));
pairList.add(new Pair<>("Bob", 30));
// Iteration and access
for (Pair<String, Integer> pair : pairList) {
System.out.println(pair.getLeft() + ": " + pair.getRight());
}
Java Standard Library Alternatives
The Java standard library provides several built-in value pair implementations:
AbstractMap.SimpleEntry (Java 6+)
List<Map.Entry<String, Integer>> entries = new ArrayList<>();
entries.add(new AbstractMap.SimpleEntry<>("Key1", 1));
entries.add(new AbstractMap.SimpleEntry<>("Key2", 2));
Map.entry (Java 9+)
List<Map.Entry<String, Integer>> entries = List.of(
Map.entry("Name1", 100),
Map.entry("Name2", 200)
);
Third-Party Library Solutions
Several popular libraries provide mature Pair implementations:
Apache Commons Lang
import org.apache.commons.lang3.tuple.Pair;
List<Pair<String, Integer>> pairs = new ArrayList<>();
pairs.add(Pair.of("Left", 1));
pairs.add(Pair.of("Right", 2));
JavaFX Pair (Java 8+)
import javafx.util.Pair;
List<Pair<String, Integer>> pairs = new ArrayList<>();
pairs.add(new Pair<>("First", 10));
pairs.add(new Pair<>("Second", 20));
Modern Java Record Implementation
Java 16 introduced record classes that provide more concise syntax for value pairs:
public record Pair<K, V>(K key, V value) {
public static <K, V> Pair<K, V> of(K key, V value) {
return new Pair<>(key, value);
}
}
// Usage example
List<Pair<String, Integer>> records = new ArrayList<>();
records.add(Pair.of("Record1", 100));
records.add(Pair.of("Record2", 200));
Performance and Memory Considerations
Based on discussions about memory efficiency in reference articles, value pair implementations need to consider object creation overhead. For high-frequency creation scenarios:
- Custom Pair class: Each new operation creates a new object
- Record classes: Similarly create new instances but with more concise syntax
- Object pooling: Consider reusing instances to reduce GC pressure
- Primitive type pairs: Eclipse Collections provides efficient primitive type pairing
Best Practice Recommendations
When choosing value pair implementations, consider:
- Java version compatibility: Select appropriate solutions based on target environment
- Immutability requirements: Immutable implementations are recommended for most scenarios
- Third-party dependencies: Evaluate costs and benefits of introducing external libraries
- Code readability: Consider using named classes instead of generic Pairs when semantics are clear
- Performance requirements: For high-frequency scenarios, consider object reuse or primitive type solutions
Conclusion
Java offers multiple choices for implementing value pair collections, ranging from simple custom Pair classes to mature solutions provided by standard libraries and third-party libraries. Developers should choose the most suitable implementation based on specific requirements, Java versions, and performance needs. With the evolution of the Java language, new features like record classes provide more modern and concise solutions for value pair processing.