What is the equivalent of the C++ Pair<L,R> in Java?

Viewed 495851

Is there a good reason why there is no Pair<L,R> in Java? What would be the equivalent of this C++ construct? I would rather avoid reimplementing my own.

It seems that 1.6 is providing something similar (AbstractMap.SimpleEntry<K,V>), but this looks quite convoluted.

36 Answers

In a thread on comp.lang.java.help, Hunter Gratzner gives some arguments against the presence of a Pair construct in Java. The main argument is that a class Pair doesn't convey any semantics about the relationship between the two values (how do you know what "first" and "second" mean ?).

A better practice is to write a very simple class, like the one Mike proposed, for each application you would have made of the Pair class. Map.Entry is an example of a pair that carry its meaning in its name.

To sum up, in my opinion it is better to have a class Position(x,y), a class Range(begin,end) and a class Entry(key,value) rather than a generic Pair(first,second) that doesn't tell me anything about what it's supposed to do.

This is Java. You have to make your own tailored Pair class with descriptive class and field names, and not to mind that you will reinvent the wheel by writing hashCode()/equals() or implementing Comparable again and again.

HashMap compatible Pair class:

public class Pair<A, B> {
    private A first;
    private B second;

    public Pair(A first, B second) {
        super();
        this.first = first;
        this.second = second;
    }

    public int hashCode() {
        int hashFirst = first != null ? first.hashCode() : 0;
        int hashSecond = second != null ? second.hashCode() : 0;

        return (hashFirst + hashSecond) * hashSecond + hashFirst;
    }

    public boolean equals(Object other) {
        if (other instanceof Pair) {
            Pair otherPair = (Pair) other;
            return 
            ((  this.first == otherPair.first ||
                ( this.first != null && otherPair.first != null &&
                  this.first.equals(otherPair.first))) &&
             (  this.second == otherPair.second ||
                ( this.second != null && otherPair.second != null &&
                  this.second.equals(otherPair.second))) );
        }

        return false;
    }

    public String toString()
    { 
           return "(" + first + ", " + second + ")"; 
    }

    public A getFirst() {
        return first;
    }

    public void setFirst(A first) {
        this.first = first;
    }

    public B getSecond() {
        return second;
    }

    public void setSecond(B second) {
        this.second = second;
    }
}

The shortest pair that I could come up with is the following, using Lombok:

@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
    private F first;
    private S second;
}

It has all the benefits of the answer from @arturh (except the comparability), it has hashCode, equals, toString and a static “constructor”.

It depends on what you want to use it for. The typical reason to do so is to iterate over maps, for which you simply do this (Java 5+):

Map<String, Object> map = ... ; // just an example
for (Map.Entry<String, Object> entry : map.entrySet()) {
  System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}

In my opinion, there is no Pair in Java because, if you want to add extra functionality directly on the pair (e.g. Comparable), you must bound the types. In C++, we just don't care, and if types composing a pair do not have operator <, the pair::operator < will not compile as well.

An example of Comparable with no bounding:

public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
    public final F first;
    public final S second;
    /* ... */
    public int compareTo(Pair<? extends F, ? extends S> that) {
        int cf = compare(first, that.first);
        return cf == 0 ? compare(second, that.second) : cf;
    }
    //Why null is decided to be less than everything?
    private static int compare(Object l, Object r) {
        if (l == null) {
            return r == null ? 0 : -1;
        } else {
            return r == null ? 1 : ((Comparable) (l)).compareTo(r);
        }
    }
}

/* ... */

Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
//Runtime error here instead of compile error!
System.out.println(a.compareTo(b));

An example of Comparable with compile-time check for whether type arguments are comparable:

public class Pair<
        F extends Comparable<? super F>, 
        S extends Comparable<? super S>
> implements Comparable<Pair<? extends F, ? extends S>> {
    public final F first;
    public final S second;
    /* ... */
    public int compareTo(Pair<? extends F, ? extends S> that) {
        int cf = compare(first, that.first);
        return cf == 0 ? compare(second, that.second) : cf;
    }
    //Why null is decided to be less than everything?
    private static <
            T extends Comparable<? super T>
    > int compare(T l, T r) {
        if (l == null) {
            return r == null ? 0 : -1;
        } else {
            return r == null ? 1 : l.compareTo(r);
        }
    }
}

/* ... */

//Will not compile because Thread is not Comparable<? super Thread>
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
System.out.println(a.compareTo(b));

This is good, but this time you may not use non-comparable types as type arguments in Pair. One may use lots of Comparators for Pair in some utility class, but C++ people may not get it. Another way is to write lots of classes in a type hierarchy with different bounds on type arguments, but there are too many possible bounds and their combinations...

another terse lombok implementation

import lombok.Value;

@Value(staticConstructor = "of")
public class Pair<F, S> {
    private final F first;
    private final S second;
}

Pair would be a good stuff, to be a basic construction unit for a complex generics, for instance, this is from my code:

WeakHashMap<Pair<String, String>, String> map = ...

It is just the same as Haskell's Tuple

Try VAVR Tuples.

Not only does vavr have a good set of tuple types, it has great support for functional programming, too.

Spring data has a Pair and can be used like below,

Pair<S, T> pair = Pair.of(S type data, T type data)

Although this question is over a decade old, I do feel the need to mention that, as of Java 14, Records can provide a very simple and light-weight solution to this problem without the need for any form of external library or dependencies.

For example, the following record class declaration would be all that's required in order to achieve the desired functionality:

record Pair<K, V>(K key, V value) { }

Such a record class could be used as so:

// Declare a pair object containing two integers
var integerIntegerPair = new Pair<>(1, 2);

// Declare a pair object containing a String and an integer
var stringIntegerPair = new Pair<>("String", 20);

// Declare a pair object containing two other pairs!
var pairPairPair = new Pair<>(new Pair<>(1, 2), new Pair<>("String", 20));
Related