Pair<L,R>
?在Java中有何等效于C++构造函数的内容?我宁愿避免重新实现我自己的构造函数。似乎Java 1.6提供了类似的内容(
AbstractMap.SimpleEntry<K,V>
),但这看起来相当复杂。comp.lang.java.help
的帖子中,Hunter Gratzner提出了一些反对Java中存在Pair
构造的论点。主要的论据是Pair
类没有传达任何关于两个值之间关系的语义(你怎么知道“first”和“second”是什么意思?)。Pair
类的每个应用编写一个非常简单的类,就像Mike建议的那样。 Map.Entry
是一个携带名称含义的pair的示例。Position(x,y)
类,一个Range(begin,end)
类和一个Entry(key,value)
类,而不是一个不告诉我任何有关其所需功能的通用Pair(first,second)
类。这是Java。您需要制作自己的定制化Pair类,使用描述性的类和字段名称,并且不必担心通过编写hashCode()/equals()或实现Comparable来重复造轮子。
SimpleImmutableEntry
。 - CurtainDogHashMap 兼容的 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;
}
}
super()
是多余的——如果你将super()
去掉,行为完全相同。通常情况下,如果选项是可选的,像这里一样,我会直接删除它。 - C. K. Young我能想到的最短的一对代码如下,使用Lombok:
@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
private F first;
private S second;
}
它具有@arturh的答案所有好处(除了可比性),它具有hashCode
,equals
,toString
和一个静态“构造函数”。
Apache Commons Lang 3.0+有几个Pair类: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
另一种实现Pair的方法。
简单工厂模式,使您不必提供类型。例如:Pair.of("hello", 1);
public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> {
public final FIRST first;
public final SECOND second;
private Pair(FIRST first, SECOND second) {
this.first = first;
this.second = second;
}
public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first,
SECOND second) {
return new Pair<FIRST, SECOND>(first, second);
}
@Override
public int compareTo(Pair<FIRST, SECOND> o) {
int cmp = compare(first, o.first);
return cmp == 0 ? compare(second, o.second) : cmp;
}
// todo move this to a helper class.
private static int compare(Object o1, Object o2) {
return o1 == null ? o2 == null ? 0 : -1 : o2 == null ? +1
: ((Comparable) o1).compareTo(o2);
}
@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 == null ? o2 == null : (o1 == o2 || o1.equals(o2));
}
@Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
of
。它让我想起了Google Guava的不可变集合。 - Jarek Przygódzkio1
强制转换为 Comparable
,尽管没有任何迹象表明它实际上会实现该接口。如果这是一个要求,那么 FIRST
类型参数应该为 FIRST extends Comparable<?>
。 - G_H你觉得 http://www.javatuples.org/index.html 怎么样呢?我发现它非常有用。
javatuples 提供了 1 到 10 个元素的 tuple 类。
Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Quartet<A,B,C,D> (4 elements)
Quintet<A,B,C,D,E> (5 elements)
Sextet<A,B,C,D,E,F> (6 elements)
Septet<A,B,C,D,E,F,G> (7 elements)
Octet<A,B,C,D,E,F,G,H> (8 elements)
Ennead<A,B,C,D,E,F,G,H,I> (9 elements)
Decade<A,B,C,D,E,F,G,H,I,J> (10 elements)
Pair
,也许50年才用一次 Triplet
。现在我使用 Lombok 并每次需要一对时创建一个仅有4行的小类。因此,“10太多”是确切的。 - maaartinusAndroid 提供了 Pair
类 (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);
}
}
Objects.equals(...)
,该方法自2011年(1.7版本)起已经存在于Java中。 - AndrewF这取决于你想用它来做什么。通常的原因是为了遍历映射,你只需这样做即可(Java 5+):
Map<String, Object> map = ... ; // just an example
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}
hashCode()
可能会为相同的 Pair 产生不一致的结果(这将导致未定义的行为,请参见 以可变字段定义等价关系)。对于特定的(非泛型)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<?, ?>
不是很确定。
如需了解此语法的更多信息,请参见确保对象实现Comparable;有关详细说明,请参见如何在Java中实现通用的max(Comparable a, Comparable b)
函数?
AbstractMap.SimpleEntry
看起来很复杂? - CurtainDog