718

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.

8
  • 10
    Why is AbstractMap.SimpleEntry convoluted? Commented Jun 28, 2012 at 1:36
  • 29
    Because of the namig, arbitrary naming one key and one value. Commented Sep 15, 2014 at 14:00
  • 2
    See also stackoverflow.com/questions/6271731/… Commented Dec 16, 2014 at 21:22
  • 2
    @sffc JavaFX isn't on any of the default classpaths in JDK7, using it requires the JFX runtime libraries be added manually. Commented May 27, 2016 at 19:40
  • 4
    @Enerccio: So, you actually state that "first" and "second" is not arbitrary, while "key" and "value" - is? Then this is one good reason for not having such class in SDK. There would be an everlasting dispute about "proper" naming. Commented Sep 11, 2016 at 19:08

34 Answers 34

424

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.

Sign up to request clarification or add additional context in comments.

8 Comments

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.
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.
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 :-)
@Dragas When i Need a Pair of values then that isnt Java...seriously?
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
|
168

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.

4 Comments

The Java-mockery would have been fine if you had pointed to the Apache Commong Lang, which contains a Pair class.
Or you could just use SimpleImmutableEntry
The most common IDEs will generate an appropriate HashCode()/equals for you.
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.
109

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

9 Comments

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).
return "(" + first.toString() + ", " + second.toString() + ")" in toString() method may throw NullPointerExceptions. This is better: return "(" + first + ", " + second + ")";
Also, either mark the pair as "final" or change the first line of equals to 'if (other != null && this.getClass() == other.getClass())'
Sorry for the random nooby question, but why do you have a call to super() in the constructor?
@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.
|
58

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

Comments

41

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

Comments

32

Another way to implement Pair with.

  • Public immutable fields, i.e. simple data structure.
  • Comparable.
  • Simple hash and equals.
  • Simple factory so you don't have to provide the types. e.g. Pair.of("hello", 1);

    public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> { public final FIRST first; public final SECOND second; private Pair(FIRST first, SECOND second) { this.first = first; this.second = second; } public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first, SECOND second) { return new Pair<FIRST, SECOND>(first, second); } @Override public int compareTo(Pair<FIRST, SECOND> o) { int cmp = compare(first, o.first); return cmp == 0 ? compare(second, o.second) : cmp; } // todo move this to a helper class. private static int compare(Object o1, Object o2) { return o1 == null ? o2 == null ? 0 : -1 : o2 == null ? +1 : ((Comparable) o1).compareTo(o2); } @Override public int hashCode() { return 31 * hashcode(first) + hashcode(second); } // todo move this to a helper class. private static int hashcode(Object o) { return o == null ? 0 : o.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Pair)) return false; if (this == obj) return true; return equal(first, ((Pair) obj).first) && equal(second, ((Pair) obj).second); } // todo move this to a helper class. private boolean equal(Object o1, Object o2) { return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2)); } @Override public String toString() { return "(" + first + ", " + second + ')'; } } 

9 Comments

I like static factory method of. It reminds of Google Guava immutable collections.
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<?>.
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?
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.
@MarioCarneiro ^ is xor, not power
|
28

How about http://www.javatuples.org/index.html I have found it very useful.

The javatuples offers you tuple classes from one to ten elements:

Unit<A> (1 element) Pair<A,B> (2 elements) Triplet<A,B,C> (3 elements) Quartet<A,B,C,D> (4 elements) Quintet<A,B,C,D,E> (5 elements) Sextet<A,B,C,D,E,F> (6 elements) Septet<A,B,C,D,E,F,G> (7 elements) Octet<A,B,C,D,E,F,G,H> (8 elements) Ennead<A,B,C,D,E,F,G,H,I> (9 elements) Decade<A,B,C,D,E,F,G,H,I,J> (10 elements) 

11 Comments

Funny, but there are at least 5 more classes than I could ever imagine to use.
@maaartinus At least 10 more than I would use.
@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.
Do we need a Bottom (0 element) class? :)
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.
|
14

android provides Pairclass (http://developer.android.com/reference/android/util/Pair.html) , here the implementation:

public class Pair<F, S> { public final F first; public final S second; public Pair(F first, S second) { this.first = first; this.second = second; } @Override public boolean equals(Object o) { if (!(o instanceof Pair)) { return false; } Pair<?, ?> p = (Pair<?, ?>) o; return Objects.equal(p.first, first) && Objects.equal(p.second, second); } @Override public int hashCode() { return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); } public static <A, B> Pair <A, B> create(A a, B b) { return new Pair<A, B>(a, b); } } 

2 Comments

Objects.equal(..) requires the Guava library.
Change it to Objects.equals(...) which has been in Java since 2011 (1.7).
12

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

2 Comments

I'm not sure a custom class would help in this case :)
"The typical reason to do so is to iterate over maps". Really?
9

The biggest problem is probably that one can't ensure immutability on A and B (see How to ensure that type parameters are immutable) so hashCode() may give inconsistent results for the same Pair after is inserted in a collection for instance (this would give undefined behavior, see Defining equals in terms of mutable fields). For a particular (non generic) Pair class the programmer may ensure immutability by carefully choosing A and B to be immutable.

Anyway, clearing generic's warnings from @PeterLawrey's answer (java 1.7) :

public class Pair<A extends Comparable<? super A>, B extends Comparable<? super B>> implements Comparable<Pair<A, B>> { public final A first; public final B second; private Pair(A first, B second) { this.first = first; this.second = second; } public static <A extends Comparable<? super A>, B extends Comparable<? super B>> Pair<A, B> of(A first, B second) { return new Pair<A, B>(first, second); } @Override public int compareTo(Pair<A, B> o) { int cmp = o == null ? 1 : (this.first).compareTo(o.first); return cmp == 0 ? (this.second).compareTo(o.second) : cmp; } @Override public int hashCode() { return 31 * hashcode(first) + hashcode(second); } // TODO : move this to a helper class. private static int hashcode(Object o) { return o == null ? 0 : o.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Pair)) return false; if (this == obj) return true; return equal(first, ((Pair<?, ?>) obj).first) && equal(second, ((Pair<?, ?>) obj).second); } // TODO : move this to a helper class. private boolean equal(Object o1, Object o2) { return o1 == o2 || (o1 != null && o1.equals(o2)); } @Override public String toString() { return "(" + first + ", " + second + ')'; } } 

Additions/corrections much welcome :) In particular I am not quite sure about my use of Pair<?, ?>.

For more info on why this syntax see Ensure that objects implement Comparable and for a detailed explanation How to implement a generic max(Comparable a, Comparable b) function in Java?

1 Comment

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?
9

Good News JavaFX has a key value Pair.

Just add JavaFX as a dependency and import javafx.util.Pair, and use simply as in C++.

Pair <Key, Value> 

e.g.

Pair <Integer, Integer> pr = new Pair<Integer, Integer>() pr.get(key);// will return corresponding value 

1 Comment

Bad news is that not everyone uses JavaFX
6

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

Comments

6

Map.Entry interface come pretty close to c++ pair. Look at the concrete implementation, like AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry First item is getKey() and second is getValue().

1 Comment

OP is already aware of this option, and it was discussed at length.
5

According to the nature of Java language, I suppose people do not actually require a Pair, an interface is usually what they need. Here is an example:

interface Pair<L, R> { public L getL(); public R getR(); } 

So, when people want to return two values they can do the following:

... //Calcuate the return value final Integer v1 = result1; final String v2 = result2; return new Pair<Integer, String>(){ Integer getL(){ return v1; } String getR(){ return v2; } } 

This is a pretty lightweight solution, and it answers the question "What is the semantic of a Pair<L,R>?". The answer is, this is an interface build with two (may be different) types, and it has methods to return each of them. It is up to you to add further semantic to it. For example, if you are using Position and REALLY want to indicate it in you code, you can define PositionX and PositionY that contains Integer, to make up a Pair<PositionX,PositionY>. If JSR 308 is available, you may also use Pair<@PositionX Integer, @PositionY Ingeger> to simplify that.

EDIT: One thing I should indicate here is that the above definition explicitly relates the type parameter name and the method name. This is an answer to those argues that a Pair is lack of semantic information. Actually, the method getL means "give me the element that correspond to the type of type parameter L", which do means something.

EDIT: Here is a simple utility class that can make life easier:

class Pairs { static <L,R> Pair<L,R> makePair(final L l, final R r){ return new Pair<L,R>(){ public L getL() { return l; } public R getR() { return r; } }; } } 

usage:

return Pairs.makePair(new Integer(100), "123"); 

4 Comments

What about equals, hashCode and toString?
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.
To implement toString you need more knowledge about the relationship between the two fields.
My point is providing a class might be better than just an interface because it can implement these things.
5

JavaFX (which comes bundled with Java 8) has the Pair< A,B > class

2 Comments

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

As many others have already stated, it really depends on the use case if a Pair class is useful or not.

I think for a private helper function it is totally legitimate to use a Pair class if that makes your code more readable and is not worth the effort of creating yet another value class with all its boiler plate code.

On the other hand, if your abstraction level requires you to clearly document the semantics of the class that contains two objects or values, then you should write a class for it. Usually that's the case if the data is a business object.

As always, it requires skilled judgement.

For your second question I recommend the Pair class from the Apache Commons libraries. Those might be considered as extended standard libraries for Java:

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html

You might also want to have a look at Apache Commons' EqualsBuilder, HashCodeBuilder and ToStringBuilder which simplify writing value classes for your business objects.

1 Comment

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

You can use javafx utility class, Pair which serves the same purpose as pair <> in c++. https://docs.oracle.com/javafx/2/api/javafx/util/Pair.html

Comments

4
Collections.singletonMap(left, rigth); 

1 Comment

If any value needs to be null this will not work.
4

another terse lombok implementation

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

Comments

3

Simple way Object [] - can be use as anу dimention tuple

2 Comments

Any dimension, yes. But: Cumbersome to create, and not type-safe.
Object[] pair = {left, right}; // Not cumbersome.
3

Despite being syntactically similar, Java and C++ have very different paradigms. Writing C++ like Java is bad C++, and writing Java like C++ is bad Java.

With a reflection based IDE like Eclipse, writing the necessarily functionality of a "pair" class is quick and simple. Create class, define two fields, use the various "Generate XX" menu options to fill out the class in a matter of seconds. Maybe you'd have to type a "compareTo" real quick if you wanted the Comparable interface.

With separate declaration / definition options in the language C++ code generators aren't so good, so hand writing little utility classes is more time consuming tedium. Because the pair is a template, you don't have to pay for functions you don't use, and the typedef facility allows assigning meaningful typenames to the code, so the objections about "no semantics" don't really hold up.

Comments

2

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

2 Comments

Now I can say, that using Pair<A,B> makes code less informative, and implementing special objects instead of using Pair is much better
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.
2

For programming languages like Java, the alternate data structure used by most programmers to represent pair like data-structures are two array, and data is accessed via the same index

example: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080

This isn't ideal as the data should be bound together, but also turn out to be pretty cheap. Also, if your use case demands storing co-ordinates then its better to build your own data structure.

I've something like this in my library

public class Pair<First,Second>{.. } 

Comments

2

You can use Google's AutoValue library - https://github.com/google/auto/tree/master/value.

You create a very small abstract class and annotate it with @AutoValue and the annotation processor generates a concrete class for you that has a value semantic.

Comments

2

Here are some libraries that have multiple degrees of tuples for your convenience:

  • JavaTuples. Tuples from degree 1-10 is all it has.
  • JavaSlang. Tuples from degree 0-8 and lots of other functional goodies.
  • jOOλ. Tuples from degree 0-16 and some other functional goodies. (Disclaimer, I work for the maintainer company)
  • Functional Java. Tuples from degree 0-8 and lots of other functional goodies.

Other libraries have been mentioned to contain at least the Pair tuple.

Specifically, in the context of functional programming which makes use of a lot of structural typing, rather than nominal typing (as advocated in the accepted answer), those libraries and their tuples come in very handy.

Comments

2

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

1 Comment

This is the best answer now that Records are available. Record patterns also allow pattern matching to unpack their contents. However, since it's so easy to define new records, and records take care of the chores of implementing equals() and hashCode() for you, it's recommended to define a new record with a meaningful name for each use, rather than a generic Pair<T, U>.
1

I noticed all the Pair implementations being strewn around here attribute meaning to the order of the two values. When I think of a pair, I think of a combination of two items in which the order of the two is of no importance. Here's my implementation of an unordered pair, with hashCode and equals overrides to ensure the desired behaviour in collections. Also cloneable.

/** * The class <code>Pair</code> models a container for two objects wherein the * object order is of no consequence for equality and hashing. An example of * using Pair would be as the return type for a method that needs to return two * related objects. Another good use is as entries in a Set or keys in a Map * when only the unordered combination of two objects is of interest.<p> * The term "object" as being a one of a Pair can be loosely interpreted. A * Pair may have one or two <code>null</code> entries as values. Both values * may also be the same object.<p> * Mind that the order of the type parameters T and U is of no importance. A * Pair&lt;T, U> can still return <code>true</code> for method <code>equals</code> * called with a Pair&lt;U, T> argument.<p> * Instances of this class are immutable, but the provided values might not be. * This means the consistency of equality checks and the hash code is only as * strong as that of the value types.<p> */ public class Pair<T, U> implements Cloneable { /** * One of the two values, for the declared type T. */ private final T object1; /** * One of the two values, for the declared type U. */ private final U object2; private final boolean object1Null; private final boolean object2Null; private final boolean dualNull; /** * Constructs a new <code>Pair&lt;T, U&gt;</code> with T object1 and U object2 as * its values. The order of the arguments is of no consequence. One or both of * the values may be <code>null</code> and both values may be the same object. * * @param object1 T to serve as one value. * @param object2 U to serve as the other value. */ public Pair(T object1, U object2) { this.object1 = object1; this.object2 = object2; object1Null = object1 == null; object2Null = object2 == null; dualNull = object1Null && object2Null; } /** * Gets the value of this Pair provided as the first argument in the constructor. * * @return a value of this Pair. */ public T getObject1() { return object1; } /** * Gets the value of this Pair provided as the second argument in the constructor. * * @return a value of this Pair. */ public U getObject2() { return object2; } /** * Returns a shallow copy of this Pair. The returned Pair is a new instance * created with the same values as this Pair. The values themselves are not * cloned. * * @return a clone of this Pair. */ @Override public Pair<T, U> clone() { return new Pair<T, U>(object1, object2); } /** * Indicates whether some other object is "equal" to this one. * This Pair is considered equal to the object if and only if * <ul> * <li>the Object argument is not null, * <li>the Object argument has a runtime type Pair or a subclass, * </ul> * AND * <ul> * <li>the Object argument refers to this pair * <li>OR this pair's values are both null and the other pair's values are both null * <li>OR this pair has one null value and the other pair has one null value and * the remaining non-null values of both pairs are equal * <li>OR both pairs have no null values and have value tuples &lt;v1, v2> of * this pair and &lt;o1, o2> of the other pair so that at least one of the * following statements is true: * <ul> * <li>v1 equals o1 and v2 equals o2 * <li>v1 equals o2 and v2 equals o1 * </ul> * </ul> * In any other case (such as when this pair has two null parts but the other * only one) this method returns false.<p> * The type parameters that were used for the other pair are of no importance. * A Pair&lt;T, U> can return <code>true</code> for equality testing with * a Pair&lt;T, V> even if V is neither a super- nor subtype of U, should * the the value equality checks be positive or the U and V type values * are both <code>null</code>. Type erasure for parameter types at compile * time means that type checks are delegated to calls of the <code>equals</code> * methods on the values themselves. * * @param obj the reference object with which to compare. * @return true if the object is a Pair equal to this one. */ @Override public boolean equals(Object obj) { if(obj == null) return false; if(this == obj) return true; if(!(obj instanceof Pair<?, ?>)) return false; final Pair<?, ?> otherPair = (Pair<?, ?>)obj; if(dualNull) return otherPair.dualNull; //After this we're sure at least one part in this is not null if(otherPair.dualNull) return false; //After this we're sure at least one part in obj is not null if(object1Null) { if(otherPair.object1Null) //Yes: this and other both have non-null part2 return object2.equals(otherPair.object2); else if(otherPair.object2Null) //Yes: this has non-null part2, other has non-null part1 return object2.equals(otherPair.object1); else //Remaining case: other has no non-null parts return false; } else if(object2Null) { if(otherPair.object2Null) //Yes: this and other both have non-null part1 return object1.equals(otherPair.object1); else if(otherPair.object1Null) //Yes: this has non-null part1, other has non-null part2 return object1.equals(otherPair.object2); else //Remaining case: other has no non-null parts return false; } else { //Transitive and symmetric requirements of equals will make sure //checking the following cases are sufficient if(object1.equals(otherPair.object1)) return object2.equals(otherPair.object2); else if(object1.equals(otherPair.object2)) return object2.equals(otherPair.object1); else return false; } } /** * Returns a hash code value for the pair. This is calculated as the sum * of the hash codes for the two values, wherein a value that is <code>null</code> * contributes 0 to the sum. This implementation adheres to the contract for * <code>hashCode()</code> as specified for <code>Object()</code>. The returned * value hash code consistently remain the same for multiple invocations * during an execution of a Java application, unless at least one of the pair * values has its hash code changed. That would imply information used for * equals in the changed value(s) has also changed, which would carry that * change onto this class' <code>equals</code> implementation. * * @return a hash code for this Pair. */ @Override public int hashCode() { int hashCode = object1Null ? 0 : object1.hashCode(); hashCode += (object2Null ? 0 : object2.hashCode()); return hashCode; } } 

This implementation has been properly unit tested and the use in a Set and Map has been tried out.

Notice I'm not claiming to release this in the public domain. This is code I've just written for use in an application, so if you're going to use it, please refrain from making a direct copy and mess about with the comments and names a bit. Catch my drift?

3 Comments

actually, check the bottom of each page: "user contributions licensed under cc-wiki"
Ah, I hadn't noticed that. Thanks for the heads-up. In that case, use code as you see fit under that license.
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.
1

com.sun.tools.javac.util.Pair is an simple implementation of a pair. It can be found in jdk1.7.0_51\lib\tools.jar.

Other than the org.apache.commons.lang3.tuple.Pair, it's not just an interface.

1 Comment

Nobody should be using the JDK internal APIs, though.
0
public class Pair<K, V> { private final K element0; private final V element1; public static <K, V> Pair<K, V> createPair(K key, V value) { return new Pair<K, V>(key, value); } public Pair(K element0, V element1) { this.element0 = element0; this.element1 = element1; } public K getElement0() { return element0; } public V getElement1() { return element1; } } 

usage :

Pair<Integer, String> pair = Pair.createPair(1, "test"); pair.getElement0(); pair.getElement1(); 

Immutable, only a pair !

3 Comments

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?
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
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.
0

Many people are posting Pair code that is usable as a key in a Map...If you're trying to use a pair as a hashing key (a common idiom), be sure to check out Guava's Table<R,C,V>: http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table. They give the following example usage, for graph edges:

Table<Vertex, Vertex, Double> weightedGraph = HashBasedTable.create(); weightedGraph.put(v1, v2, 4); weightedGraph.put(v1, v3, 20); weightedGraph.put(v2, v3, 5); weightedGraph.row(v1); // returns a Map mapping v2 to 4, v3 to 20 weightedGraph.column(v3); // returns a Map mapping v1 to 20, v2 to 5 

A Table maps two keys to a single value, and provides efficient lookups for both types of keys alone as well. I've started using this data structure instead of a Map<Pair<K1,K2>, V> in many parts of my code. There are array, tree, and other implementations for both dense and sparse uses, with the option of specifying your own intermediate map classes.

6 Comments

How does this answer the question?
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.
Where is the pair data structure in the code you are proposing?
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."
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.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.