What is the equivalent of the C++ Pair<L,R> in Java?
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
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, 2021Comments
-
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 over 14 yearsYou 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ä over 14 yearsreturn "(" + first.toString() + ", " + second.toString() + ")" in toString() method may throw NullPointerExceptions. This is better: return "(" + first + ", " + second + ")";
-
Illarion Kovalchuk about 14 yearsNow I can say, that using Pair<A,B> makes code less informative, and implementing special objects instead of using Pair is much better
-
sargas almost 14 yearsAlso, either mark the pair as "final" or change the first line of equals to 'if (other != null && this.getClass() == other.getClass())'
-
curot almost 14 yearsSorry for the random nooby question, but why do you have a call to super() in the constructor?
-
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 about 13 yearsI like static factory method
of
. It reminds of Google Guava immutable collections. -
G_H about 13 yearsYou are at some point casting
o1
toComparable
, even though nothing indicates it will actually implement that interface. If that is a requirement, theFIRST
type parameter should beFIRST extends Comparable<?>
. -
Nikita Rybak about 13 yearsI'm not sure a custom class would help in this case :)
-
amara almost 13 yearsactually, check the bottom of each page: "user contributions licensed under cc-wiki"
-
G_H almost 13 yearsAh, I hadn't noticed that. Thanks for the heads-up. In that case, use code as you see fit under that license.
-
Daniel Lubarov almost 13 yearsIt 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 over 12 years"The typical reason to do so is to iterate over maps". Really?
-
Has QUIT--Anony-Mousse over 12 yearsOh, 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 writePair.createPair((Object)"abc", (Object)"def")
with your code? -
Bastiflew over 12 yearsyou 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 over 12 yearsNo, 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 over 12 yearsAny dimension, yes. But: Cumbersome to create, and not type-safe.
-
haylem about 12 yearsThe Java-mockery would have been fine if you had pointed to the Apache Commong Lang, which contains a Pair class.
-
Michael Piefel about 12 yearsThe 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 about 12 yearsI'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 about 12 yearsCan be any, like CompareableUtils or Comparables.
-
CurtainDog almost 12 yearsOr you could just use
SimpleImmutableEntry
-
maaartinus over 11 yearsFunny, but there are at least 5 more classes than I could ever imagine to use.
-
maaartinus over 11 yearsBetter 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 over 11 years
&& otherPair.first != null
and&& otherPair.second != null
are reduntant (causethis.first/sec == otherPair.first/sec
would be true if both were null) -
Mr_and_Mrs_D over 11 yearsThe 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 over 11 yearsHow does this answer the question?
-
Andrew Mao over 11 yearsMany 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 over 11 yearsWhere is the pair data structure in the code you are proposing?
-
Andrew Mao over 11 yearsThere 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 over 11 yearsNo 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 over 11 yearsThe 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 implementequals
andhashCode
, specifically for this purpose. TheTable
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 almost 11 years31 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 over 10 yearsThey doesnt come with the java standard library, do they?
-
Boann about 10 years@maaartinus At least 10 more than I would use.
-
maaartinus about 10 years@Boann: OK, I stay corrected. I used to use
Pair
and could imagine to useTriplet
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 about 10 yearsOn 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 changePair
toPair<?, ?>
in both cases. Is that okay? -
Keegan almost 9 yearsOP is already aware of this option, and it was discussed at length.
-
Earth Engine over 8 yearsDo we need a
Bottom (0 element)
class? :) -
sffc over 8 yearsThe 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 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 over 8 years@MarioCarneiro Java String.hashCode() used 31 has a multiply prime long before eclipse was started.
-
Michał Zieliński over 8 years@MarioCarneiro ^ is xor, not power
-
Michał Zieliński over 8 years@PeterLawrey the situation with strings is different - the alphabet size is typically smaller (char vs int)
-
arviman almost 8 yearsWow 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 over 7 yearsCant' believe someone actually took the time to write that.
-
jpangamarca over 7 yearsNobody should be using the JDK internal APIs, though.
-
Ian over 7 yearsGratzner 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 over 7 yearsI 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 over 7 yearsIf 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 almost 7 yearsWhat about
equals
,hashCode
andtoString
? -
Earth Engine almost 7 yearswell, 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 almost 7 yearsTo implement
toString
you need more knowledge about the relationship between the two fields. -
sdgfsdh almost 7 yearsMy point is providing a
class
might be better than just aninterface
because it can implement these things. -
Haakon Løtveit over 6 yearsYou 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 over 6 yearsThe 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 over 6 years
Objects.equal(..)
requires the Guava library. -
java-addict301 over 6 yearsThe most common IDEs will generate an appropriate HashCode()/equals for you.
-
MAGx2 over 6 yearsThanks for this link. In my opinion it is useful. Big plus is that this lib does not have any other dependencies.
-
John Henckel over 6 yearsI 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 about 6 yearsI 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 almost 6 years@JohnHenckel It's like an instructor putting easy questions on the exam because he wants everyone to succeed. Dumb.
-
Andrey Tyukin over 5 yearsA 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 over 5 yearsChange it to
Objects.equals(...)
which has been in Java since 2011 (1.7). -
AndrewF over 5 yearsThat 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 over 5 yearsNifty! Liked it!
-
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 about 5 years@Dragas When i Need a Pair of values then that isnt Java...seriously?
-
Mushtaq Jameel about 5 yearsWe 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 over 4 yearsObject.equals? That might be simpler than if (x == y)/if (x != null && x.equals(y)) stuff.
-
Dan about 4 yearsAs 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 almost 4 yearsBad news is that not everyone uses JavaFX
-
tsh almost 4 yearsYou know... You just need a
Pair
, and then you can writePair<A, Pair<B, Pair<C, Pair<D, Pair<E, Pair<F, Pair<G, Pair<H, Pair<I, J>>>>>>>>>
when you needDecade
. -
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 over 3 yearsintroducing me to lombok, priceless.
-
VimNing over 3 years@tsh: Did you say
Headache<...>
? -
Christopher over 2 yearsObject[] pair = {left, right}; // Not cumbersome.