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

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


当前回答

虽然这个问题已经有十多年的历史了,但我觉得有必要提一下,从Java 14开始,Records可以为这个问题提供非常简单和轻量级的解决方案,而不需要任何形式的外部库或依赖项。

例如,以下记录类声明将是实现所需功能所需的全部内容:

record Pair<K, V>(K key, V value) { }

这样一个记录类可以这样使用:

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

其他回答

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

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

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

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

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

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

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