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

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


当前回答

这是Java。您必须使用描述性的类名和字段名创建自己定制的Pair类,不要介意通过编写hashCode()/equals()或一次又一次地实现Comparable来重新发明轮子。

其他回答

这是Java。您必须使用描述性的类名和字段名创建自己定制的Pair类,不要介意通过编写hashCode()/equals()或一次又一次地实现Comparable来重新发明轮子。

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

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

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

在我看来,Java中没有Pair,因为如果你想直接在Pair上添加额外的功能(例如Comparable),你必须绑定类型。在c++中,我们不在乎,如果组成一个pair的类型没有操作符<,则pair::operator <也不会被编译。

Comparable的一个例子:

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

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

这很好,但是这次您不能在Pair中使用不可比较的类型作为类型参数。 你可能会在一些实用程序类中使用很多comparator for Pair,但是c++的人可能不会理解。另一种方法是在类型层次结构中编写很多类,在类型参数上有不同的边界,但是有太多可能的边界和它们的组合……

您可以使用谷歌的AutoValue库- https://github.com/google/auto/tree/master/value。

您创建一个非常小的抽象类,并使用@AutoValue注释它,注释处理器为您生成一个具有值语义的具体类。

另一个简洁的lombok实现

import lombok.Value;

@Value(staticConstructor = "of")
public class Pair<F, S> {
    private final F first;
    private final S second;
}