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

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


当前回答

为了方便起见,以下是一些具有多级元组的库:

JavaTuples。它只有1-10度的元组。 JavaSlang。0-8度的元组和许多其他功能性的东西。 jOOλ。0-16度的元组和其他一些功能性的好东西。(免责声明,我在维修公司工作) Functional Java。0-8度的元组和许多其他功能性的东西。

已经提到的其他库至少包含Pair元组。

具体来说,在函数式编程的上下文中,它使用了大量的结构类型,而不是名义类型(正如公认答案中提倡的那样),这些库及其元组非常方便。

其他回答

最大的问题可能是不能确保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)函数?

Brian Goetz, Paul Sandoz和Stuart Marks在Devoxx'14的QA环节中解释了原因。

一旦值类型被引入,在标准库中使用泛型对类就会变成技术债。

请参见:Java SE 8是否有对或元组?

Apache Commons Lang 3.0+有几个Pair类: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html

android提供了Pairclass (http://developer.android.com/reference/android/util/Pair.html),这里实现:

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

正如许多人已经指出的那样,Pair类是否有用实际上取决于用例。

我认为,对于私有帮助函数,如果使用Pair类可以使代码更具可读性,并且不值得花费精力创建另一个包含所有锅炉代码的值类,那么使用Pair类是完全合法的。

另一方面,如果您的抽象级别要求您清楚地记录包含两个对象或值的类的语义,那么您应该为它编写一个类。如果数据是业务对象,通常就是这种情况。

一如既往,这需要熟练的判断。

对于你的第二个问题,我推荐Apache Commons库中的Pair类。这些可能被认为是Java的扩展标准库:

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

你可能还想看看Apache Commons的EqualsBuilder、HashCodeBuilder和ToStringBuilder,它们简化了为业务对象编写值类的过程。