开发者

Using Pairs or 2-tuples in Java [duplicate]

This question already has answers here: A Java collection of value pairs? (tuples?) (21 answers) Closed 6 years ago.

My Hashtable in Java would benefit from a value having a tuple structure. What data structure can I use in Java to do that?

Hashta开发者_开发知识库ble<Long, Tuple<Set<Long>,Set<Long>>> table = ...


I don't think there is a general purpose tuple class in Java but a custom one might be as easy as the following:

public class Tuple<X, Y> { 
  public final X x; 
  public final Y y; 
  public Tuple(X x, Y y) { 
    this.x = x; 
    this.y = y; 
  } 
} 

Of course, there are some important implications of how to design this class further regarding equality, immutability, etc., especially if you plan to use instances as keys for hashing.


javatuples is a dedicated project for tuples in Java.

Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)


Apache Commons provided some common java utilities including a Pair. It implements Map.Entry, Comparable and Serializable.


If you are looking for a built-in Java two-element tuple, try AbstractMap.SimpleEntry.


As an extension to @maerics nice answer, I've added a few useful methods:

public class Tuple<X, Y> { 
    public final X x; 
    public final Y y; 
    public Tuple(X x, Y y) { 
        this.x = x; 
        this.y = y; 
    }

    @Override
    public String toString() {
        return "(" + x + "," + y + ")";
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }

        if (!(other instanceof Tuple)){
            return false;
        }

        Tuple<X,Y> other_ = (Tuple<X,Y>) other;

        // this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed.
        return other_.x.equals(this.x) && other_.y.equals(this.y);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((x == null) ? 0 : x.hashCode());
        result = prime * result + ((y == null) ? 0 : y.hashCode());
        return result;
    }
}


Another 2 cents : Starting with Java 7, there is now a class for this in standard Lib : javafx.util.Pair.

And Yes, It is standard Java, now that JavaFx is included in the JDK :)


Here's this exact same question elsewhere, that includes a more robust equals, hash that maerics alludes to:

http://groups.google.com/group/comp.lang.java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b

That discussion goes on to mirror the maerics vs ColinD approaches of "should I re-use a class Tuple with an unspecific name, or make a new class with specific names each time I encounter this situation". Years ago I was in the latter camp; I've evolved into supporting the former.


With lombok it's easy to declare a Pair class:

@Data(staticConstructor = "of")
public class Pair<A, B> {
    private final A left;
    private final B right;
}

This will generates getters, static constructor named "of", equals(), hashcode() and toString().

see @Data documentation for more information


Android Tuple Utils

This object provides a sensible implementation of equals(), returning true if equals() is true on each of the contained objects.


Create a class that describes the concept you're actually modeling and use that. It can just store two Set<Long> and provide accessors for them, but it should be named to indicate what exactly each of those sets is and why they're grouped together.


Though the article is pretty old now, and though I understand that I'm not really very helpful, I think the proposal described in Adding tuples to Java: a study in lightweight data structures, would have been nice in mainstream Java.

You can do things like:

int a;
char b;
float c;
[a,b,c] = [3,'a',2.33];

or

[int,int,char] x = [1,2,'a'];

or

public [int,boolean] Find(int i)
{
  int idx = FindInArray(A,i);
  return [idx,idx>=0];
}

[idx, found] = Find(7);

Here tuples are:

  • Defined as primitive types - no templates/generics
  • Stack-allocated if declared locally
  • Assigned using pattern-matching

This approach increases

  • Performance
  • Readability
  • Expressiveness


To supplement @maerics's answer, here is the Comparable tuple:

import java.util.*;

/**
 * A tuple of two classes that implement Comparable
 */
public class ComparableTuple<X extends Comparable<? super X>, Y extends Comparable<? super Y>>
       extends Tuple<X, Y>
       implements Comparable<ComparableTuple<X, Y>>
{
  public ComparableTuple(X x, Y y) {
    super(x, y);
  }

  /**
   * Implements lexicographic order
   */
  public int compareTo(ComparableTuple<X, Y> other) {
    int d = this.x.compareTo(other.x);
    if (d == 0)
      return this.y.compareTo(other.y);
    return d;
  }
}


You can use Google Guava Table


I will start from a general point of view about tuples in Java and finish with an implication for your concrete problem.

1) The way tuples are used in non-generic languages is avoided in Java because they are not type-safe (e.g. in Python: tuple = (4, 7.9, 'python')). If you still want to use something like a general purpose tuple (which is not recommended), you should use Object[] or List<Object> and cast the elements after a check with instanceof to assure type-safety.

Usually, tuples in a certain setting are always used the same way with containing the same structure. In Java, you have to define this structure explicitly in a class to provide well-defined, type-safe values and methods. This seems annoying and unnecessairy at first but prevents errors already at compile-time.

2) If you need a tuple containing the same (super-)classes Foo, use Foo[], List<Foo>, or List<? extends Foo> (or the lists's immutable counterparts). Since a tuple is not of a defined length, this solution is equivalent.

3) In your case, you seem to need a Pair (i.e. a tuple of well-defined length 2). This renders maerics's answer or one of the supplementary answers the most efficient since you can reuse the code in the future.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜