ChatGPT解决这个技术问题 Extra ChatGPT

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

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.

Why is AbstractMap.SimpleEntry convoluted?
Because of the namig, arbitrary naming one key and one value.
@sffc JavaFX isn't on any of the default classpaths in JDK7, using it requires the JFX runtime libraries be added manually.
@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.

F
Felipe

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.


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

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.


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.
@JohnHenckel It's like an instructor putting easy questions on the exam because he wants everyone to succeed. Dumb.
a
arturh

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

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

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


Nifty! Liked it!
introducing me to lombok, priceless.
M
Mr_and_Mrs_D

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 implements Comparable> { public final FIRST first; public final SECOND second; private Pair(FIRST first, SECOND second) { this.first = first; this.second = second; } public static Pair of(FIRST first, SECOND second) { return new Pair(first, second); } @Override public int compareTo(Pair 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 + ')'; } }


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 for 2D map, you will get many collisions. For example (a*65497)^b would be better suited.
@MarioCarneiro ^ is xor, not power
c
cyberoblivion

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)

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

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

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

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

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

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?


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?
M
Mark Rotteveel

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

Bad news is that not everyone uses JavaFX
M
MaxBuzz

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


N
Nikunj Bhagat

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


OP is already aware of this option, and it was discussed at length.
E
Earth Engine

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

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

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


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.
P
Peter Goetz

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.


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.
S
Sathyanarayanan Ganesan

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


D
Denis Arkharov
Collections.singletonMap(left, rigth);

M
Matt Broekhuis

another terse lombok implementation

import lombok.Value;

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

T
Testus

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


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

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.


I
Illarion Kovalchuk

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


Now I can say, that using Pair 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.
S
Swapneel Patil

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

S
Shahar

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.


C
Community

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.


C
Community

Brian Goetz, Paul Sandoz and Stuart Marks explain why during QA session at Devoxx'14.

Having generic pair class in standard library will turn into technical debt once value types introduced.

See also: Does Java SE 8 have Pairs or Tuples?


G
G_H

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?


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.
L
Luís Cardoso

If anyone wants a dead-simple and easy to use version I made my available at https://github.com/lfac-pt/Java-Pair. Also, improvements are very much welcome!


m
masterxilo

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.


Nobody should be using the JDK internal APIs, though.
B
Bastiflew
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 !


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.