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

489,891

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

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”.

Solution 5

Apache Commons Lang 3.0+ has a few Pair classes: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html

Share:
489,891
David Segonds
Author by

David Segonds

Participating in developing innovative software for over 25 years is nice. Founding an organization to address frictions and inefficiencies prevailing during the crafting, promotion, and evaluation of commercial offers is nicer. Of course, this all needs to be developed, and while my title says CEO, I am heavily involved as a technical founder.

Updated on September 17, 2021

Comments

  • David Segonds
    David Segonds over 2 years

    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.

  • hansvb
    hansvb over 14 years
    You probably want to delete the setters, and make first and second final, thus making the pair immutable. (If someone changed the components after using them as a hash key, weird things will happen).
  • Juha Syrjälä
    Juha Syrjälä over 14 years
    return "(" + first.toString() + ", " + second.toString() + ")" in toString() method may throw NullPointerExceptions. This is better: return "(" + first + ", " + second + ")";
  • Illarion Kovalchuk
    Illarion Kovalchuk about 14 years
    Now I can say, that using Pair<A,B> makes code less informative, and implementing special objects instead of using Pair is much better
  • sargas
    sargas almost 14 years
    Also, either mark the pair as "final" or change the first line of equals to 'if (other != null && this.getClass() == other.getClass())'
  • curot
    curot almost 14 years
    Sorry for the random nooby question, but why do you have a call to super() in the constructor?
  • C. K. Young
    C. K. Young over 13 years
    @Ibrahim: In this case, it's superfluous---the behaviour is exactly the same if you took the super() out. Normally I'd just lop it off if it's optional, like it is here.
  • Jarek Przygódzki
    Jarek Przygódzki about 13 years
    I like static factory method of. It reminds of Google Guava immutable collections.
  • G_H
    G_H about 13 years
    You are at some point casting o1 to Comparable, even though nothing indicates it will actually implement that interface. If that is a requirement, the FIRST type parameter should be FIRST extends Comparable<?>.
  • Nikita Rybak
    Nikita Rybak about 13 years
    I'm not sure a custom class would help in this case :)
  • amara
    amara almost 13 years
    actually, check the bottom of each page: "user contributions licensed under cc-wiki"
  • G_H
    G_H almost 13 years
    Ah, I hadn't noticed that. Thanks for the heads-up. In that case, use code as you see fit under that license.
  • Daniel Lubarov
    Daniel Lubarov almost 13 years
    It is optional, but only in the sense that the compiler will insert the call for you if you don't write it explicitly. Even when the super class is Object, there is a method java/lang/Object/<init>()V and it does need to be called.
  • Bennett McElwee
    Bennett McElwee over 12 years
    "The typical reason to do so is to iterate over maps". Really?
  • Has QUIT--Anony-Mousse
    Has QUIT--Anony-Mousse over 12 years
    Oh, wow. Another one? Try using yours with more complex Generics - at some point, it will fail to infer the appropriate types. Plus, the following should be possible: Pair<Object, Object> pair = Pair.createPair("abc", "def") but I figure one needs to write Pair.createPair((Object)"abc", (Object)"def") with your code?
  • Bastiflew
    Bastiflew over 12 years
    you can replace the static method by this : @SuppressWarnings("unchecked") public static <K, V, X, Y> Pair<X, Y> createPair(K key, V value) { return new Pair<X, Y>((X) key, (Y) value); } but i don't know if it's a good practice
  • Has QUIT--Anony-Mousse
    Has QUIT--Anony-Mousse over 12 years
    No, that will likely only screw up things even more. In my experience, at least one of the compilers (try java6, java7, javadoc and eclipse java compiler) will complain. The traditional new Pair<Object, Object>("abc", "def") was the most reliable in my experiments.
  • Michael Piefel
    Michael Piefel over 12 years
    Any dimension, yes. But: Cumbersome to create, and not type-safe.
  • haylem
    haylem about 12 years
    The Java-mockery would have been fine if you had pointed to the Apache Commong Lang, which contains a Pair class.
  • Michael Piefel
    Michael Piefel about 12 years
    The updated URL is commons.apache.org/lang/api-release/index.html?org/apache/… since commons-lang3 is out of beta. This is even shorter than my own Lombok solution if you already use commons-lang 3.
  • Admin
    Admin about 12 years
    I'm not a java guy, so please forgive me for my ignorance, but what sort of helper classes were you thinking of in the TODO comments?
  • Vishy
    Vishy about 12 years
    Can be any, like CompareableUtils or Comparables.
  • CurtainDog
    CurtainDog almost 12 years
    Or you could just use SimpleImmutableEntry
  • maaartinus
    maaartinus over 11 years
    Funny, but there are at least 5 more classes than I could ever imagine to use.
  • maaartinus
    maaartinus over 11 years
    Better or worse. Imagine you have a function combining its two arguments (e.g. merging graphs into one) and need to cache it. Here, Pair is optimal as there's no special semantics. Having a clear name for a clear concept is good, but looking for a name where "first" and "second" work well is not.
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 11 years
    && otherPair.first != null and && otherPair.second != null are reduntant (cause this.first/sec == otherPair.first/sec would be true if both were null)
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 11 years
    The question is about a C++ equivalent pair - which is ordered. Also I think that as long as one has a reference to Pair's object and those are mutable inserting Pairs in collections might lead to undefined behavior.
  • jogojapan
    jogojapan over 11 years
    How does this answer the question?
  • Andrew Mao
    Andrew Mao over 11 years
    Many people are posting Pair code that is usable as a key in Maps, so I thought I'd post a more direct approach. I'll update my post for context.
  • jogojapan
    jogojapan over 11 years
    Where is the pair data structure in the code you are proposing?
  • Andrew Mao
    Andrew Mao over 11 years
    There is no pair at all, because this data structure obviates the need to create a pair as a hashing key. I decided to post because of the other answers - "it depends on what you want to use [the pair] for."
  • jogojapan
    jogojapan over 11 years
    No hard feelings, but I just don't think this answers the question. Using pairs to represent key/value in a hash is one very special way of using it, but, firstly, this would rather be a counter argument to implementing a generalized pair data structure (because a 'hash-entry' data structure would be more appropriate -- and that's exactly what Java's HashMap.Entry is), and secondly, your example isn't about key-values, but about triples stored in a bindex-style map, and even the data structure that represents the triple isn't made explicit in your answer.
  • Andrew Mao
    Andrew Mao over 11 years
    The pair in this case is not for a (key, value) pair. It's for a pair of objects that represent a unique key. It's definitely not the same as a Map.Entry. If you look at the other answers, there are a lot of proposed pairs that implement equals and hashCode, specifically for this purpose. The Table doesn't store a triple. It maps a pair of keys to a value and has lookup functions specifically for that purpose.
  • Michał Zieliński
    Michał Zieliński almost 11 years
    31 is a bad constant for hashCode. For example, if you use HashMap keyed by Pair<Integer,Integer> for 2D map, you will get many collisions. For example (a*65497)^b would be better suited.
  • pr00thmatic
    pr00thmatic over 10 years
    They doesnt come with the java standard library, do they?
  • Boann
    Boann about 10 years
    @maaartinus At least 10 more than I would use.
  • maaartinus
    maaartinus about 10 years
    @Boann: OK, I stay corrected. I used to use Pair and could imagine to use Triplet maybe once every 50 years. Now I use Lombok and create a tiny 4-line class every time I need a pair. So "10 too much" is exact.
  • pratnala
    pratnala about 10 years
    On the line where you write Pair otherPair = (Pair) other, Eclipse gives me a friendly warning saying, References to generic type Pair<A, B> should be parameterized. And it suggests to change Pair to Pair<?, ?> in both cases. Is that okay?
  • Keegan
    Keegan almost 9 years
    OP is already aware of this option, and it was discussed at length.
  • Earth Engine
    Earth Engine over 8 years
    Do we need a Bottom (0 element) class? :)
  • sffc
    sffc over 8 years
    The implementation of hashCode in javafx.util.Pair can lead to collisions on trivial cases. Using it in HashMap/HashTable will still work since Java checks for equality of values in addition to hash codes, but it's something to be aware of.
  • Mario Carneiro
    Mario Carneiro over 8 years
    @MichałZieliński I think the 31 is there because 31 is Eclipse's favorite prime number (appears when you use "generate hashCode() and equals()". Computing a power would be too expensive for a general-use class like this though.
  • Vishy
    Vishy over 8 years
    @MarioCarneiro Java String.hashCode() used 31 has a multiply prime long before eclipse was started.
  • Michał Zieliński
    Michał Zieliński over 8 years
    @MarioCarneiro ^ is xor, not power
  • Michał Zieliński
    Michał Zieliński over 8 years
    @PeterLawrey the situation with strings is different - the alphabet size is typically smaller (char vs int)
  • arviman
    arviman almost 8 years
    Wow this is ugly. I know they're trying to make it explicit, but a Tuple with overloaded params like in C# would have been nicer.
  • jpangamarca
    jpangamarca over 7 years
    Cant' believe someone actually took the time to write that.
  • jpangamarca
    jpangamarca over 7 years
    Nobody should be using the JDK internal APIs, though.
  • Ian
    Ian over 7 years
    Gratzner is splitting hairs. We're quite happy to return a single value as a primitive or built-in class without encapsulating it in a class. If we were to return a tuple of a dozen elements no one would disagree it should have its own class. Somewhere in the middle is a (fuzzy) dividing line. I think our lizard brains can cope with Pairs easily enough.
  • Clément
    Clément over 7 years
    I agree with Ian. Java lets you return int; it doesn't force you to create an alias for int every time you use one. Pairs are not very different.
  • marcus
    marcus over 7 years
    If we could unpack a pair directly to your local variables, or forward it to a method that takes two arguments, Pair would be a useful class. Since we can't unpack it like this, creating a meaningful class and keeping the values together doesn't look too bad. And, if you really want a pair despite the limitations, there's always Object[2] + casts :-)
  • sdgfsdh
    sdgfsdh almost 7 years
    What about equals, hashCode and toString?
  • Earth Engine
    Earth Engine almost 7 years
    well, this is just a minimal implementation. If you need more than that you can write some helper functions to make it easier, but still you need to write the code.
  • Earth Engine
    Earth Engine almost 7 years
    To implement toString you need more knowledge about the relationship between the two fields.
  • sdgfsdh
    sdgfsdh almost 7 years
    My point is providing a class might be better than just an interface because it can implement these things.
  • Haakon Løtveit
    Haakon Løtveit over 6 years
    You ought to have an @lombok.Value annotation there and you get equals, hashCode, getters, private final on fields, and a toString method as well for free. At that point the Pair<T,Z> thing is strictly inferior, since it wouldn't handle primitive types well.
  • Haakon Løtveit
    Haakon Løtveit over 6 years
    The thing is that if you disagree with Gratzner, then there's Pair implementations in several places. Apache Commons and Guava both have it IIRC. Use those. But to put something in the main Java libraries means that it's A Noble And Approved Way Of Doing Things (with capitalization) and since people don't agree on it, we shouldn't put it there. There's enough cruft in the old libs as is, let's not needlessly put more there.
  • Markus L
    Markus L over 6 years
    Objects.equal(..) requires the Guava library.
  • java-addict301
    java-addict301 over 6 years
    The most common IDEs will generate an appropriate HashCode()/equals for you.
  • MAGx2
    MAGx2 over 6 years
    Thanks for this link. In my opinion it is useful. Big plus is that this lib does not have any other dependencies.
  • John Henckel
    John Henckel over 6 years
    I agree. "Because this is Java" is a good answer. Remember that the Java language is intentionally deprived of certain (cough c++) features that are confusing to the average programmer. That is why Java does not allow you to redefine operators. Nor does it allow multiple inheritance. Bottom line is, if some stupid programmer is likely to abuse it, then Java will make it hard to do.
  • 463035818_is_not_a_number
    463035818_is_not_a_number about 6 years
    I dont get the java "noble and approved way" thingy. Lets say I definitely dont want to create a new class then the easiest alternative is to use an array with two entries which is by far worse than a pair in terms of conveying semantics
  • stillanoob
    stillanoob almost 6 years
    @JohnHenckel It's like an instructor putting easy questions on the exam because he wants everyone to succeed. Dumb.
  • Andrey Tyukin
    Andrey Tyukin over 5 years
    A unary (not zero-ary!) Unit. And what for? They didn't even get their Latin right, why is it "Pair" and not "Doublet" or something... That's just stupid.
  • AndrewF
    AndrewF over 5 years
    Change it to Objects.equals(...) which has been in Java since 2011 (1.7).
  • AndrewF
    AndrewF over 5 years
    That is a very standard and commonly-recommended hashCode implementation. Collisions should be expected by any code that calls hashCode(). Note that Java itself doesn't call this method. It is for user code, including libraries.
  • Ahmet Ipkin
    Ahmet Ipkin over 5 years
    Nifty! Liked it!
  • Dragas
    Dragas about 5 years
    @user463035818 Each language has its purpose. Seems to me like you don't need java at all, but some other language that is not as constraint heavy and lets you hack around.
  • 463035818_is_not_a_number
    463035818_is_not_a_number about 5 years
    @Dragas When i Need a Pair of values then that isnt Java...seriously?
  • Mushtaq Jameel
    Mushtaq Jameel about 5 years
    We use maps and list all the time in Java, if semantics were the most important aspect, then don't maps and list (being generic data types) obfuscate the meaning too, a Map<String, Int> and a Pair of Pair<String,int> looks similar
  • Paul Stelian
    Paul Stelian over 4 years
    Object.equals? That might be simpler than if (x == y)/if (x != null && x.equals(y)) stuff.
  • Dan
    Dan about 4 years
    As Java Integers are 32 bit, won't multiplying the first hashcode by 31 mean that it overflows? Would it not be better to perform an exclusive OR?
  • Michał Dobi Dobrzański
    Michał Dobi Dobrzański almost 4 years
    Bad news is that not everyone uses JavaFX
  • tsh
    tsh almost 4 years
    You know... You just need a Pair, and then you can write Pair<A, Pair<B, Pair<C, Pair<D, Pair<E, Pair<F, Pair<G, Pair<H, Pair<I, J>>>>>>>>> when you need Decade.
  • Swift - Friday Pie
    Swift - Friday Pie over 3 years
    @TimGoodman Gratzner in spartan outfit shouting that while kicking a new student into the pit of standard name paths
  • Orwellophile
    Orwellophile over 3 years
    introducing me to lombok, priceless.
  • VimNing
    VimNing over 3 years
    @tsh: Did you say Headache<...>?
  • Christopher
    Christopher over 2 years
    Object[] pair = {left, right}; // Not cumbersome.