我有一个具有Map< String,Object>的类。字段(键是字符串,值是已正确实现“等于”方法进行比较的对象)。
我想以这样的方式覆盖此类的equals,如果Maps在键和值之间具有相等的映射,则只返回true。
这是我的尝试:
// Assumes that the Object values in maps have correctly implemented the equals method.
private boolean mapsEqual(Map<String, Object> attributes)
{
if (this.attributes_.keySet().size() != attributes.keySet().size() ||
this.attributes_.values().size() != attributes.values().size())
return false;
for (String key : attributes.keySet()) {
if (!this.attributes_.keySet().contains(key))
return false;
if (!this.attributes_.get(key).equals(attributes.get(key)))
return false;
}
return true;
}
但是,当多次添加相同的键或从映射中删除键时,此实现失败(值的大小测试失败,因为它们计算重复项,并且在删除值时不会调整大小。)
似乎我的情况应该足够常见,以找到与我的案件相关的信息,但我找不到任何信息。这种情况是否有任何遗留代码或广泛接受的解决方案?任何帮助或工作解决方案表示赞赏。
答案 0 :(得分:1)
即使我不是100%确定它能解决你的问题(但它根本不适合评论),我会把它作为答案。
首先,重复我的评论:Map
界面禁止地图有重复键或每个键有多个值。因此,任何适当的实施(例如java.util.HashMap
)都不允许这样做。通常情况下,如果发生这种情况,他们只会替换该值。
此外,对我而言,equals
的规范似乎正在做你想要的。同样,正确的实现必须符合该规范。
所以,这里有什么意义:如果你正在编写自己正在实现Map
的类,那么它就不能允许重复键(像get
这样的方法就没有意义了)。如果您使用的是HashMap
等内置实现,则无论如何都会替换这些值。
现在您说您遇到了keySet()
和values()
的尺寸问题。我认为你应该添加会导致这种行为的示例代码。以下工作对我来说很好:
Map<String, String> map = new HashMap<String, String>();
map.put("Foo", "Bar");
System.out.println(map.keySet().size()); // 1
System.out.println(map.values().size()); // 1
map.put("Foo", "Baz"); // the HashMap will merely replace the old value
System.out.println(map.keySet().size()); // still 1
System.out.println(map.values().size()); // still 1
删除密钥当然会改变大小。到目前为止,根据您的解释,我不认为您认为这是一个问题。
关于equals
,您可能只想查看HashMap
的实现,可以找到 here :
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<K,V> m = (Map<K,V>) o;
if (m.size() != size())
return false;
try {
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key)==null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
考虑以下示例:
Map<String, String> map1 = new HashMap<String, String>();
map1.put("Foo", "Bar");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("Foo", "Bar");
System.out.println(map1.equals(map2)); // true
答案 1 :(得分:0)
首先,你抱怨你的地图有重复的密钥......不可能(除非你使用了严重破坏的实现)。
这应该这样做:
public boolean equals(Object o) {
if (!(o instanceof MyClass))
return false;
MyClass that = (MyClass)o;
if (map.size() != that.map.size())
return false;
for (Map.Entry<String, Object> entry : map) {
Object a = entry.getValue();
Object b = that.map.get(entry.getKey());
if ((a == null ^ b == null) || (a == null && !a.equals(b)))
return false;
}
return true;
}