A Java collection of value pairs? (tuples?)

AbstractMap.SimpleEntry

Easy you are looking for this:

java.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();

How can you fill it?

java.util.Map.Entry<String,Integer> pair1=new java.util.AbstractMap.SimpleEntry<>("Not Unique key1",1);
java.util.Map.Entry<String,Integer> pair2=new java.util.AbstractMap.SimpleEntry<>("Not Unique key2",2);
pairList.add(pair1);
pairList.add(pair2);

This simplifies to:

Entry<String,Integer> pair1=new SimpleEntry<>("Not Unique key1",1);
Entry<String,Integer> pair2=new SimpleEntry<>("Not Unique key2",2);
pairList.add(pair1);
pairList.add(pair2);

And, with the help of a createEntry method, can further reduce the verbosity to:

pairList.add(createEntry("Not Unique key1", 1));
pairList.add(createEntry("Not Unique key2", 2));

Since ArrayList isn't final, it can be subclassed to expose an of method (and the aforementioned createEntry method), resulting in the syntactically terse:

TupleList<java.util.Map.Entry<String,Integer>> pair = new TupleList<>();
pair.of("Not Unique key1", 1);
pair.of("Not Unique key2", 2);

Java 9+

In Java 9, you can simply write: Map.entry(key, value) to create an immutable pair.

Note: this method does not allow keys or values to be null. If you want to allow null values, for example, you'd want to change this to: Map.entry(key, Optional.ofNullable(value)).


Java 8+

In Java 8, you can use the more general-purpose javafx.util.Pair to create an immutable, serializable pair. This class does allow null keys and null values. (In Java 9, this class is included in the javafx.base module). EDIT: As of Java 11, JavaFX has been decoupled from the JDK, so you'd need the additional maven artifact org.openjfx:javafx-base.


Java 6+

In Java 6 and up, you can use the more verbose AbstractMap.SimpleImmutableEntry for an immutable pair, or AbstractMap.SimpleEntry for a pair whose value can be changed. These classes also allow null keys and null values, and are serializable.


Android

If you're writing for Android, just use Pair.create(key, value) to create an immutable pair.


Apache Commons

Apache Commons Lang provides the helpful Pair.of(key, value) to create an immutable, comparable, serializable pair.


Eclipse Collections

If you're using pairs that contain primitives, Eclipse Collections provides some very efficient primitive pair classes that will avoid all the inefficient auto-boxing and auto-unboxing.

For instance, you could use PrimitiveTuples.pair(int, int) to create an IntIntPair, or PrimitiveTuples.pair(float, long) to create a FloatLongPair.


Hand-rolled implementations

As of Java 16, records have come out of preview status, so you can now do:

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);
    }
}

The above implementation will have a big advantage in the future, as it'll allow you to do record deconstruction.

Prior to Java 16, you can achieve the same semantics with Project Lombok:

@Value(staticConstructor = "of")
public class Pair<K, V> {
    K key;
    V value;
}

or, with the following verbosity (which, unlike the class listed in the accepted answer, guards against NullPointerExceptions, and has a robust hashCode() implementation identical to that of Records1):

import java.util.Objects;

public class Pair<K, V> {

    public final K key;
    public final V value;

    private Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public static <K, V> Pair<K, V> of(K key, V value) {
        return new Pair<>(key, value);
    }

    public boolean equals(Object o) {
        return o instanceof Pair && Objects.equals(key, ((Pair<?,?>)o).key) && Objects.equals(value, ((Pair<?,?>)o).value);
    }

    public int hashCode() {
        return 31 * Objects.hashCode(key) + Objects.hashCode(value);
    }

    public String toString() {
        return key + "=" + value;
    }
}

1 Tested on OpenJDK 17


The Pair class is one of those "gimme" generics examples that is easy enough to write on your own. For example, off the top of my head:

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());
  }

}

And yes, this exists in multiple places on the Net, with varying degrees of completeness and feature. (My example above is intended to be immutable.)

Tags:

Java