【发布时间】:2021-05-27 04:08:33
【问题描述】:
我使用 Map.Entry 为 Java 中的 Pair 类编写了以下代码。有没有人有任何改进它的建议?对我来说,该类需要满足的最重要标准是构造 Pair 很容易,并且 .equals 可以按照我想要的方式工作(Pair 中的两个对象以相同的顺序相等意味着对)。该代码似乎按预期运行,并且尚未用于任何占用我系统内存的内容,但我们将不胜感激。
import java.util.*;
public class Pair {
// Return a map entry (key-value pair) from the specified values
public static <T, U> Map.Entry<T, U> of(T first, U second) {
return new AbstractMap.SimpleEntry<>(first, second);
}
private Map.Entry entry;
public Pair (Object x, Object y) {
Set<Map.Entry> entries = new HashSet<>();
entries.add(Pair.of(x, y));
Object[] setArray = entries.toArray();
this.entry = (Map.Entry) setArray[0];
}
public Object getKey() {
return entry.getKey();
}
public Object getValue() {
return entry.getValue();
}
@Override
public boolean equals(Object o)
{
if (o instanceof Pair) {
Pair pair = (Pair) o;
return ( (entry.getKey().equals(pair.getKey())) && (entry.getValue().equals(pair.getValue())) );
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(entry.getKey(), entry.getValue());
}
@Override
public String toString() {
return String.format( "(" +entry.getKey().toString() + ", " + entry.getValue().toString() + ")" );
}
}
我一直在考虑使用 Collections.singletonMap 而不是 Map.Entry。
到目前为止,我已经使用以下代码成功测试了我的代码:
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<Pair, Integer> testMap = new HashMap<>();
Pair onThrup = new Pair(1, 3);
System.out.println(onThrup); //Prints contents of Pair, not hash
testMap.put(onThrup, 7);
Pair unoTres = new Pair(1, 3);
System.out.println(onThrup.equals(unoTres));
System.out.println(testMap.containsKey(onThrup));
System.out.println(unoTres.hashCode() == onThrup.hashCode());
System.out.println(testMap.containsKey(unoTres)); // Should be, and is, true
}
}
【问题讨论】:
-
我确实希望能够运行一个构造新 Pairs 的循环,同时重复使用相同的变量名,如 p,而不会出现问题。 .equals() 下的哈希相等和相等应该基于 Pair 的内容,以便在新 Pair 上运行 HashMap.containsKey 将返回 true,如果它与作为键添加的 Pair 具有相同的值之前的 HashMap 的键值对。我相信我这里的代码确实可以做到这一点,但是如果有人对格式或效率有建议,可能会有更好的方法来编写类。
-
我认为您可以为该对必须持有的每个对象使用一个字段。它将消除对 Map.Entry 的需要。您还可以使用泛型来制作您的类签名,例如
Pair<T1, T2>。无论如何,我真的不明白你为什么使用成对构造函数中的集合。可以简化。 -
如果您希望它可用作映射键,则必须覆盖 Pair 类中的 equals 和 hashCode 方法。需要了解的可以看this tutorial。
-
您还可以使用第三方 Pair 实现 - 来自 Apache Commons 的
ImmutablePair或来自 Vavr 的Tuple2 -
我使用了 Set,因为 Entry 是抽象的,无法实例化。我相信 hashCode 和 equals 的覆盖是成功的。