Java曾经有过Pair类吗?

Didn't Java once have a Pair class?

本问题已经有最佳答案,请猛点这里访问。

我记得不正确,或曾经做过Java,曾经提供过Pair类作为其API的一部分?


标准框架中没有Pair,但Apache Commons Lang非常接近"标准",它有一对。


<5233>

Java 1.6和upper有两个Map.Entry接口的实现,将一个键与一个值配对:

  • AbstractMap.SimpleEntry
  • AbstractMap.SimpleImmutableEntry

UML diagram of SimpleEntry & SimpleImmutableEntry classes inheriting from Map.Entry interface

例如

1
2
3
4
5
6
Map.Entry < Month, Boolean > pair =
    new AbstractMap.SimpleImmutableEntry <>(
        Month.AUGUST ,
        Boolean.TRUE
    )
;

pair.toString(): AUGUST=true

我需要存储对时使用它(如大小和对象集合)。

这件作品来自我的生产代码:

1
2
3
4
5
6
7
8
9
10
11
public Map<L1Risk, Map.Entry<int[], Map<L2Risk, Map.Entry<int[], Map<L3Risk, List<Event>>>>>>
        getEventTable(RiskClassifier classifier) {
    Map<L1Risk, Map.Entry<int[], Map<L2Risk, Map.Entry<int[], Map<L3Risk, List<Event>>>>>> l1s = new HashMap<>();
    Map<L2Risk, Map.Entry<int[], Map<L3Risk, List<Event>>>> l2s = new HashMap<>();
    Map<L3Risk, List<Event>> l3s = new HashMap<>();
    List<Event> events = new ArrayList<>();
    ...
    map.put(l3s, events);
    map.put(l2s, new AbstractMap.SimpleImmutableEntry<>(l3Size, l3s));
    map.put(l1s, new AbstractMap.SimpleImmutableEntry<>(l2Size, l2s));
}

代码看起来很复杂,但不是Map.Entry,而是限制为对象数组(大小为2)并丢失类型检查...


对类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Pair<K, V> {

    private final K element0;
    private final V element1;

    public static <K, V> Pair<K, V> createPair(K element0, V element1) {
        return new Pair<K, V>(element0, element1);
    }

    public Pair(K element0, V element1) {
        this.element0 = element0;
        this.element1 = element1;
    }

    public K getElement0() {
        return element0;
    }

    public V getElement1() {
        return element1;
    }

}

用法:

1
2
3
Pair<Integer, String> pair = Pair.createPair(1,"test");
pair.getElement0();
pair.getElement1();

永恒,只有一对!


这里有很多实现,但总是缺少一些东西,覆盖等于和哈希方法。

这是这个类的更完整版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
 * Container to ease passing around a tuple of two objects. This object provides a sensible
 * implementation of equals(), returning true if equals() is true on each of the contained
 * objects.
 */

public class Pair<F, S> {
    public final F first;
    public final S second;

    /**
     * Constructor for a Pair.
     *
     * @param first the first object in the Pair
     * @param second the second object in the pair
     */

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    /**
     * Checks the two objects for equality by delegating to their respective
     * {@link Object#equals(Object)} methods.
     *
     * @param o the {@link Pair} to which this one is to be checked for equality
     * @return true if the underlying objects of the Pair are both considered
     *         equal
     */

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equals(p.first, first) && Objects.equals(p.second, second);
    }

    /**
     * Compute a hash code using the hash codes of the underlying objects
     *
     * @return a hashcode of the Pair
     */

    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    /**
     * Convenience method for creating an appropriately typed pair.
     * @param a the first object in the Pair
     * @param b the second object in the pair
     * @return a Pair that is templatized with the types of a and b
     */

    public static <A, B> Pair <A, B> create(A a, B b) {
        return new Pair<A, B>(a, b);
    }
}


这应该有所帮助。

总结一下:泛型Pair类没有任何特殊的语义,你也可以需要一个Tripplet类等。因此Java的开发人员不包含泛型Pair但建议写特殊类(不是那么难),如Point(x,y)Range(start, end)Map.Entry(key, value)


不,但已被多次要求。


许多第三方库都有它们的Pair版本,但Java从未有过这样的类。最接近的是内部接口java.util.Map.Entry,它公开了一个不可变的键属性和一个可能的可变值属性。


如果你想要一对(不应该是键值对)只是将两个通用数据保存在一起,上面的解决方案都没有真正方便,因为第一个(或所谓的Key)无法更改(在Apache Commons Lang的Pair和AbstractMap.SimpleEntry中都没有) )。他们有自己的理由,但你仍然需要能够改变这两个组件。这是一个Pair类,可以在其中设置两个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class Pair<First, Second> {
    private First first;
    private Second second;

    public Pair(First first, Second second) {
        this.first = first;
        this.second = second;
    }

    public void setFirst(First first) {
        this.first = first;
    }

    public void setSecond(Second second) {
        this.second = second;
    }

    public First getFirst() {
        return first;
    }

    public Second getSecond() {
        return second;
    }

    public void set(First first, Second second) {
        setFirst(first);
        setSecond(second);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Pair pair = (Pair) o;

        if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
        if (second != null ? !second.equals(pair.second) : pair.second != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = first != null ? first.hashCode() : 0;
        result = 31 * result + (second != null ? second.hashCode() : 0);
        return result;
    }
}


这看起来很奇怪。我发现这个帖子,也认为我过去见过一个,但在Javadoc找不到它。

我可以看到Java开发人员关于使用专用类的观点,并且泛型Pair类的存在可能导致开发人员变得懒惰(使思想消失!)

然而,根据我的经验,毫无疑问,你正在建模的东西真的只是一对东西,而且对于这两个对子之间的关系提出了一个有意义的名字,实际上比仅仅是上场更痛苦用它。因此,我们只需要创建一个实际上是锅炉板代码的"定制"类 - 可能称为"配对"。

这可能是一个滑坡,但是Pair和Triplet类将覆盖很大一部分用例。


不,但JavaFX拥有它。

参看Stack Overflow:Java Pair类实现