6

我只是想确保我的代码使用对象作为键是安全的。Integer这是一个简短的示例:

Integer int1 = new Integer(1337);
Integer int2 = new Integer(1337);

if (int1 == int2) {
    System.out.println("true");
} else {
    System.out.println("false");
}

if (int1.equals(int2)) {
    System.out.println("true");
} else {
    System.out.println("false");
}

Map<Integer, Object> map = new HashMap<Integer, Object>();
map.put(int1, null);
map.put(int2, null);

System.out.println(map.size());

代码将输出

false
true
1

这就是我所期待的,参考文献不同,但它们彼此相等。现在我对地图的行为感兴趣。

  • 是否保证像 Map 或 Set 这样的集合会通过内容而不是参考来比较键?
  • 还是取决于实际的实现,例如HashMap
4

8 回答 8

7

该方法equals被调用,因此它是比较的内容。

关于你上面的两个问题:

给定两个对象o1and o2(为了简化,我们假设o1!=nulland o2!=null),hasp map 最终必须确定它们是否具有相同的值。(最终,因为还HaspMap检查是否具有相同的哈希值,但这在您的问题的上下文中并不重要)。它通过调用方法来做到这一点。只要为假,这两个对象就被认为是两个不同的键。o1o2equals()o1.equals(o2)HashMap

HashSet还调用equals()以确定元素是否已包含在集合中,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add%28E%29

TreeMap另一方面,必须比较两个对象,并确定它们是否相等,或者哪个更大。它通过调用compareTo(). 因此,它的返回值o1.compareTo(o2)很重要(或者,如果您使用构造函数http://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap %28java.util.Comparator%29,使用了比较器)。

因此,可以保证的是,在HashMap和中HashSet,该方法equals()用于区分对象,而在TreeMap,该方法compareTo()中。

于 2012-12-19T12:35:36.140 回答
6

Q1: - 是否保证像 Map 或 Set 这样的集合会通过内容而不是参考来比较键?

A1: - 不,Collection、Map 和 Set 是接口。他们唯一保证的是可能的方法的合同。

Q2: - 取决于实际的实现,比如HashMap?

A2:是的。类如何处理比较是开发人员的决定。

HashMap 使用两个东西来分配它们的对象

首先 - 是Object#hashCode(),用于计算指数。

第二个 - 是Object#equals(),那是使用然后散列colison有地方。

于 2012-12-19T12:50:12.277 回答
3

如果您打开实现java.util.AbstractMap您可以看到键和值方程Object#equals在任何地方都使用方法检查。map 内部实际比较的内容取决于Object#equals方法的键/值实现。

于 2012-12-19T12:36:41.537 回答
1

这里的 Integer 是 Waraper 的最终类,它是被覆盖的equals()方法,所以它只会比较内容。

所以如果使用 Integers are Any wrapper class 没有问题Map

假设如果您想使用 Custome Class 作为键您需要覆盖equals() and hashcode()方法以避免重复Map

于 2012-12-19T12:37:02.007 回答
0

它实际上取决于您equals()为.KMap

尝试对 a 做同样的Map<Object,String>事情,看看会发生什么(提示:为了Object's 相等,它们实际上必须是同一个对象)

干杯

于 2012-12-19T12:36:46.513 回答
0

第一个比较两个不同的对象(引用)--> false。

第二个比较(相等)这些对象的值 --> true

Hashmap 使用对象的 equals 和 hascode 方法来确定唯一键。所以你有两次插入相同的键,导致一个剩余的元素。第二个。看看Map#put javadoc 看看发生了什么。

于 2012-12-19T12:37:06.360 回答
0

在 hashmap 的情况下,使用 equals() 和 hashcode() 方法比较键。

在上面的示例中,hashcode() 和 equals() 都在 Integer 类中被覆盖。当 HashMap 比较两个键时,首先它获取该对象的 hashcode() ,然后对该对象调用 equals 方法,并且键具有相同的 hashcode 值。

于 2012-12-19T12:41:16.847 回答
0

将项目放入 HashMap(以及扩展的 HashSet)时,使用 hashCode(由简单的线性函数转换)来确定项目应放置在其内部集合中的位置。

Then in the determined location it searches for an identical object (among all items stored there) using (o1 == o2 || o1.equals(o2)), the #equals function is called if references differ, which is a performance improvement to simple #equals call. If identical item is found, its assigned value is replaced with the new one, if not, the new item is simply added to internal collection.

于 2014-04-23T07:32:49.187 回答