Java中没有Pair<L,R>,有什么好理由吗?与这个c++构造等价的是什么?我宁愿避免重新实现我自己的。

似乎1.6提供了类似的东西(AbstractMap.SimpleEntry<K,V>),但这看起来相当复杂。


当前回答

我能想到的最短的一对是以下,使用Lombok:

@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
    private F first;
    private S second;
}

它拥有@arturh答案的所有好处(除了可比性),它有hashCode, equals, toString和一个静态“构造函数”。

其他回答

简单的方法Object[] -可以作为一个几何体元组使用

HashMap兼容Pair类:

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

我能想到的最短的一对是以下,使用Lombok:

@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
    private F first;
    private S second;
}

它拥有@arturh答案的所有好处(除了可比性),它有hashCode, equals, toString和一个静态“构造函数”。

@Andreas Krey的回答其实很好。任何Java给你带来困难的事情,你都不应该去做。

在我的经验中,Pair最常见的用途是一个方法的多个返回值和hashmap中的values(通常由字符串索引)。

在后一种情况下,我最近使用了一个数据结构,类似这样:

class SumHolder{MyObject trackedObject, double sum};

这是您的整个“Pair”类,与通用的“Pair”类的代码数量几乎相同,但具有描述性名称的优势。它可以在它使用的方法中定义,这将消除公共变量等典型问题。换句话说,对于这种用法,它绝对比一对更好(由于命名的成员),不会更差。

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.

我能看到的另一种情况是使用一个公共api,为当前包之外的调用者提供返回值。为此,我只创建一个真正的对象——最好是不可变的。最终,调用者将共享此返回值,并且使其可变可能会出现问题。这是Pair对象更糟糕的另一种情况——大多数Pair不能被设置为不可变的。

所有这些情况的另一个优点是——java类扩展,我的sum类需要第二个sum和“Created”标记,当我完成时,我将不得不扔掉Pair并使用其他东西,但如果Pair有意义,我的4个值的类至少仍然有意义。

最大的问题可能是不能确保A和B上的不可变(参见如何确保类型参数是不可变的),因此hashCode()在插入到集合后可能会为相同的Pair给出不一致的结果(这将给出未定义的行为,参见定义可变字段中的equals)。对于一个特定的(非泛型的)Pair类,程序员可以通过仔细选择a和B为不可变来确保不可变性。

不管怎样,从@PeterLawrey的回答中清除泛型的警告(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 + ')';
    }
}

补充/更正非常欢迎:)特别是我不太确定我使用Pair<?, ? >。

有关为什么这种语法的更多信息,请参阅确保对象实现可比和详细解释如何在Java中实现一个通用的max(可比a,可比b)函数?