713

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
David Segonds
  • 83,345
  • 10
  • 45
  • 66
  • 10
    Why is `AbstractMap.SimpleEntry` convoluted? – CurtainDog Jun 28 '12 at 01:36
  • See my answer http://stackoverflow.com/a/16089164/173149 where I use **AbstractMap.SimpleImmutableEntry** without any problem (complicated example). – gavenkoa Apr 18 '13 at 17:10
  • `SimpleEntry` has three methods not inherited from `Object`. Why should it be "convoluted"? – haansn08 Aug 08 '14 at 19:04
  • 29
    Because of the namig, arbitrary naming one key and one value. – Enerccio Sep 15 '14 at 14:00
  • 2
    See also http://stackoverflow.com/questions/6271731/whats-the-best-way-to-return-a-pair-of-values-in-java – Raedwald Dec 16 '14 at 21:22
  • If using Java 8, `import javafx.util.Pair` solves your problems. – sffc Oct 23 '15 at 11:52
  • 2
    @sffc JavaFX isn't on any of the default classpaths in JDK7, using it requires the JFX runtime libraries be added manually. – Cord Rehn May 27 '16 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. – fdreger Sep 11 '16 at 19:08

37 Answers37

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.

Felipe
  • 16,649
  • 11
  • 68
  • 92
Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
  • 184
    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. – Ian Oct 25 '16 at 09:31
  • 37
    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. – Clément Dec 04 '16 at 18:20
  • 5
    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 :-) – marcus Dec 14 '16 at 00:41
  • 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. – Haakon Løtveit Aug 11 '17 at 09:38
  • 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 – 463035818_is_not_an_ai Apr 05 '18 at 09:29
  • @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. – Dragas Feb 17 '19 at 07:39
  • 2
    @Dragas When i Need a Pair of values then that isnt Java...seriously? – 463035818_is_not_an_ai Feb 17 '19 at 09:59
  • 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 and a Pair of Pair looks similar – Mushtaq Jameel Feb 26 '19 at 12:34
167

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.

Andreas Krey
  • 6,426
  • 2
  • 18
  • 13
  • 24
    The Java-mockery would have been fine if you had pointed to the Apache Commong Lang, which contains a Pair class. – haylem Feb 29 '12 at 09:10
  • 6
    Or you could just use `SimpleImmutableEntry` – CurtainDog Jun 28 '12 at 01:40
  • The most common IDEs will generate an appropriate HashCode()/equals for you. – java-addict301 Nov 13 '17 at 15:12
  • 3
    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. – John Henckel Nov 15 '17 at 15:01
  • 1
    @JohnHenckel It's like an instructor putting easy questions on the exam because he wants everyone to succeed. Dumb. – stillanoob Jul 24 '18 at 15:16
  • @TimGoodman Gratzner in spartan outfit shouting that while kicking a new student into the pit of standard name paths – Swift - Friday Pie Sep 27 '20 at 14:19
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;
    }
}
arturh
  • 6,056
  • 4
  • 39
  • 48
  • 145
    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). – Thilo Aug 28 '09 at 09:21
  • 22
    return "(" + first.toString() + ", " + second.toString() + ")" in toString() method may throw NullPointerExceptions. This is better: return "(" + first + ", " + second + ")"; – Juha Syrjälä Sep 01 '09 at 08:31
  • 6
    Also, either mark the pair as "final" or change the first line of equals to 'if (other != null && this.getClass() == other.getClass())' – sargas May 29 '10 at 00:45
  • 9
    Sorry for the random nooby question, but why do you have a call to super() in the constructor? – Ibrahim Jun 16 '10 at 19:09
  • 6
    @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. K. Young Sep 30 '10 at 18:58
  • 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/()V` and it does need to be called. – Daniel Lubarov Jul 04 '11 at 02:38
  • `&& 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 Dec 01 '12 at 14:20
  • On the line where you write `Pair otherPair = (Pair) other`, Eclipse gives me a friendly warning saying, `References to generic type Pair should be parameterized`. And it suggests to change `Pair` to `Pair, ?>` in both cases. Is that okay? – pratnala Mar 12 '14 at 15:28
  • Object.equals? That might be simpler than if (x == y)/if (x != null && x.equals(y)) stuff. – Paul Stelian Nov 13 '19 at 21:57
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”.

Community
  • 1
  • 1
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
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

masterxilo
  • 2,503
  • 1
  • 30
  • 35
Matunos
  • 529
  • 4
  • 3
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 + ')';
        }
    }
    
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 10
    I like static factory method `of`. It reminds of **Google Guava** immutable collections. – Jarek Przygódzki Apr 05 '11 at 19:35
  • 7
    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>`. – G_H Apr 20 '11 at 17:36
  • 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? –  Mar 29 '12 at 14:41
  • Can be any, like CompareableUtils or Comparables. – Peter Lawrey Mar 29 '12 at 19:08
  • 3
    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. – Michał Zieliński Jun 29 '13 at 18:58
  • @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. – Mario Carneiro Jan 12 '16 at 19:18
  • @MarioCarneiro Java String.hashCode() used 31 has a multiply prime long before eclipse was started. – Peter Lawrey Jan 12 '16 at 20:39
  • 1
    @MarioCarneiro ^ is xor, not power – Michał Zieliński Jan 13 '16 at 21:03
  • @PeterLawrey the situation with strings is different - the alphabet size is typically smaller (char vs int) – Michał Zieliński Jan 13 '16 at 21:03
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)
cyberoblivion
  • 669
  • 7
  • 23
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);
    }
}
sherpya
  • 4,890
  • 2
  • 34
  • 50
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());
}
cletus
  • 616,129
  • 168
  • 910
  • 942
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?

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • 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? – Dan Mar 15 '20 at 00:20
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
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
RAJAN_PARMAR
  • 139
  • 2
  • 9
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().

Nikunj Bhagat
  • 61
  • 1
  • 1
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...

MaxBuzz
  • 69
  • 1
  • 1
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");
Earth Engine
  • 10,048
  • 5
  • 48
  • 78
5

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

CarrKnight
  • 2,768
  • 2
  • 23
  • 25
  • 1
    The [implementation of hashCode in javafx.util.Pair](http://hg.openjdk.java.net/openjfx/8/master/rt/file/f89b7dc932af/modules/base/src/main/java/javafx/util/Pair.java#l91) 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. – sffc Oct 23 '15 at 11:51
  • 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. – AndrewF Oct 15 '18 at 18:53
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

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.

Peter Goetz
  • 99
  • 1
  • 4
  • The updated URL is http://commons.apache.org/lang/api-release/index.html?org/apache/commons/lang3/tuple/Pair.html since commons-lang3 is out of beta. This is even shorter than my own Lombok solution if you already use commons-lang 3. – Michael Piefel Mar 13 '12 at 13:59
4
Collections.singletonMap(left, rigth);
4

another terse lombok implementation

import lombok.Value;

@Value(staticConstructor = "of")
public class Pair<F, S> {
    private final F first;
    private final S second;
}
Matt Broekhuis
  • 1,985
  • 2
  • 26
  • 35
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.

gerardw
  • 5,822
  • 46
  • 39
3

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

Testus
  • 104
  • 1
  • 8
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>{.. }
Swapneel Patil
  • 2,403
  • 1
  • 16
  • 6
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

Illarion Kovalchuk
  • 5,774
  • 8
  • 42
  • 54
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.

Shahar
  • 426
  • 1
  • 4
  • 3
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.

Community
  • 1
  • 1
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
2

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?

Community
  • 1
  • 1
user2418306
  • 2,352
  • 1
  • 22
  • 33
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.

masterxilo
  • 2,503
  • 1
  • 30
  • 35
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?

G_H
  • 11,739
  • 3
  • 38
  • 82
  • 3
    actually, check the bottom of each page: "user contributions licensed under cc-wiki" – amara Apr 30 '11 at 17:44
  • Ah, I hadn't noticed that. Thanks for the heads-up. In that case, use code as you see fit under that license. – G_H May 02 '11 at 13:47
  • 1
    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. – Mr_and_Mrs_D Dec 02 '12 at 14:26
1

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!

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.

Andrew Mao
  • 35,740
  • 23
  • 143
  • 224
  • How does this answer the question? – jogojapan Dec 28 '12 at 04:47
  • 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. – Andrew Mao Dec 28 '12 at 15:19
  • Where is the pair data structure in the code you are proposing? – jogojapan Dec 28 '12 at 15:32
  • 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." – Andrew Mao Dec 28 '12 at 18:04
  • 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. – jogojapan Dec 29 '12 at 04:35
  • 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. – Andrew Mao Dec 29 '12 at 20:29
0

With new version of Lombok you can compile that cute class:

@Value(staticConstructor = "of") public class Pair <E> {
  E first, second;
}

and use it like: Pair<Value> pairOfValues = Pair.of(value1, value2);

Dominik
  • 331
  • 1
  • 4
  • 12
0

The answer by @Andreas Krey is actually good. Anything Java makes difficult, you probably shouldn't be doing.

The most common uses of Pair's in my experience have been multiple return values from a method and as VALUES in a hashmap (often indexed by strings).

In the latter case, I recently used a data structure, something like this:

class SumHolder{MyObject trackedObject, double sum};

There is your entire "Pair" class, pretty much the same amount of code as a generic "Pair" but with the advantage of descriptive names. It can be defined in-line right in the method it's used which will eliminate typical problems with public variables and the like. In other words, it's absolutely better than a pair for this usage (due to the named members) and no worse.

If you actually want a "Pair" for the key of a hashmap you are essentially creating a double-key index. I think this may be the one case where a "Pair" is significantly less code. It's not really easier because you could have eclipse generate equals/hash on your little data class, but it would be a good deal more code. Here a Pair would be a quick fix, but if you need a double-indexed hash who's to say you don't need an n-indexed hash? The data class solution will scale up, the Pair will not unless you nest them!

So the second case, returning from a method, is a bit harder. Your class needs more visibility (the caller needs to see it too). You can define it outside the method but inside the class exactly as above. At that point your method should be able to return a MyClass.SumHolder object. The caller gets to see the names of the returned objects, not just a "Pair". Note again that the "Default" security of package level is pretty good--it's restrictive enough that you shouldn't get yourself into too much trouble. Better than a "Pair" object anyway.

The other case I can see a use for Pairs is a public api with return values for callers outside your current package. For this I'd just create a true object--preferably immutable. Eventually a caller will share this return value and having it mutable could be problematic. This is another case of the Pair object being worse--most pairs cannot be made immutable.

Another advantage to all these cases--the java class expands, my sum class needed a second sum and a "Created" flag by the time I was done, I would have had to throw away the Pair and gone with something else, but if the pair made sense, my class with 4 values still makes at least as much sense.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • 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 thing is strictly inferior, since it wouldn't handle primitive types well. – Haakon Løtveit Aug 11 '17 at 09:37
0

Try VAVR Tuples.

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

Noel Yap
  • 18,822
  • 21
  • 92
  • 144
0

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

Pair<S, T> pair = Pair.of(S type data, T type data)
Arefe
  • 11,321
  • 18
  • 114
  • 168
0

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));
HomeworkHopper
  • 300
  • 1
  • 12
0

Recommend to go with Apache commons ImmutablePair.

ImmutablePair<L, R> immutablePairOfLandR = ImmutablePair.of(leftElementValue,rightElementValue);

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

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 !

Bastiflew
  • 1,136
  • 3
  • 18
  • 31
  • 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 pair = Pair.createPair("abc", "def")` but I figure one needs to write `Pair.createPair((Object)"abc", (Object)"def")` with your code? – Has QUIT--Anony-Mousse Dec 09 '11 at 11:01
  • you can replace the static method by this : `@SuppressWarnings("unchecked") public static Pair createPair(K key, V value) { return new Pair((X) key, (Y) value); }` but i don't know if it's a good practice – Bastiflew Dec 09 '11 at 11:31
  • 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("abc", "def")` was the most reliable in my experiments. – Has QUIT--Anony-Mousse Dec 10 '11 at 13:57