Generic pair class
只是尝试这个问题,我在过去的考试试卷中发现,这样我就可以为即将进行的Java考试做准备。
提供用于表示事物对的通用类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 | public class Pair<firstThing, secondThing>{ private firstThing first;//first member of pair private secondThing second;//second member of pair public Pair(firstThing first, secondThing second){ this.first = first; this.second = second; } public void setFirst(firstThing first){ this.first = first; } public void setSecond(secondThing second) { this.second = second; } public thing getFirst() { return this.first; } public thing getSecond() { return this.second; } } |
几乎。我写的是这样的:
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 | public class Pair<F, S> { private F first; //first member of pair private S second; //second member of pair public Pair(F first, S second) { this.first = first; this.second = second; } public void setFirst(F first) { this.first = first; } public void setSecond(S second) { this.second = second; } public F getFirst() { return first; } public S getSecond() { return second; } } |
编辑:我同意@ karmakaze的评论。代码应跳过setter并进行第一和第二次final以使其保持不变。
对类的需求通常会出现在更大的项目中 - 我即将(重新)为当前项目实现一个(因为以前的实现是不可访问的)。
通常我将它变成一个不可变的POJO,具有创建实例的便利功能。例如:
1 2 3 4 5 6 | public class Pair<T,U> { public final T first; public final U second; public static <T,U> Pair<T,U> of(T first, U second); } |
这样最终用户就可以写:
1 | return Pair.of (a, b); |
和
1 2 3 | Pair<A,B> p = someThing (); doSomething (p.first); doSomethingElse (p.second); |
如上所述,Pair类还应该实现hashCode(),equals(),optional-but-useful toString(),可能是clone()和compareTo(),用于T和U支持的地方 - 尽管额外的工作需要描述Pair类如何支持这些契约。
这是Android SDK的一个实现
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.equal(p.first, first) && Objects.equal(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); } } |
您可以查看标准Java类AbstractMap.SimpleEntry和AbstractMap.SimpleImmutableEntry的实现。 google来源非常简单:
- http://www.docjar.com/html/api/java/util/AbstractMap.java.html
- http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractMap.java
我想没有。引用:
"the class should be parameterised
over two types..."
我认为他们期望:
1 | public class Pair<ThingA, ThingB> |
编辑后,它看起来不错。
但是,您确实应该实现
吸气剂坏了
1 2 3 4 5 6 7 | public thing getFirst() { return thing.first; } public thing getSecond() { return thing.second; } |
通常,通用Pair类型有两个泛型类型参数,而不是一个 - 所以你可以有(比方说)一个
我还建议您考虑类型参数比"事物"更常规的名称。例如,您可以使用
Apache Commons Lang有一个通用的对实现
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
不,您是否尝试过编码以确定它是否有效?
您似乎错过了这部分要求:
The class should be parameterised over two types one for the first member and one for the second member of the pair.
这意味着该类应该被定义为更像:
其他方法也相应更新。 (顺便说一下,我已经使用T1和T2来引用类型,按惯例,使用短 - 1或2个char - 标识符)。
也,
和
不会像在你的例子中那样工作,
完成更改后,对其进行编码,然后编写单元测试或简单的测试工具来检查它是否有效。
The class should be parameterised over two types one for the first member and one for the second member of the pair.
您只有一个参数。
你需要像
我实现了类似的东西,但使用静态构建器和链式setter
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 | public class Pair<R, L> { private R left; private L right; public static <K,V> Pair<K, V> of(K k, V v) { return new Pair<K,V>(k, v); } public Pair() {} public Pair(R key, L value) { this.left(key); this.right(value); } public R left() { return left; } public Pair<R, L> left(R key) { this.left = key; return this; } public L right() { return right; } public Pair<R, L> right(L value) { this.right = value; return this; } } |
我的双版本。这也处理比较。
PS:大部分代码都来自AOSP。
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 58 59 60 61 62 63 64 65 66 67 | package util; import java.util.Objects; public class Pair<F extends Comparable<F>, S extends Comparable> implements Comparable<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 extends Comparable<A>, B extends Comparable> Pair<A, B> create(A a, B b) { return new Pair<>(a, b); } @Override public int compareTo(Pair<F, S> that) { int cmp = this.first.compareTo(that.first); if (cmp == 0) cmp = this.second.compareTo(that.second); return cmp; } } |
快速改进:用
快速修复getter:
1 2 3 4 5 6 7 | public T getFirst() { return first; } public T getSecond() { return second; } |
一个要求是允许两对不同类型的成员。所以类签名应如下所示:
1 2 3 4 5 | public Pair<S,T> { private S first; private T second; //... } |