1

假设我想把一个键和它的值放在一个 Map 中。

我相信这是 Java 所做的:

  1. 获取key的Hashcode,查看map中是否有相同hashcode的key。

  2. 如果没有具有相同 Hashcode 的键,则可以将键放入 Map。

  3. 如果有一个具有相同 Hashcode 的键,则使用 equals 来确定该键是否可以放入 Map 中。

我的问题是为什么不在这个过程中使用==而不是equals

4

5 回答 5

11

做你建议的事情会打破equals/hashCode串联的整个概念。两者equalshashCode都会变得无用,甚至不应该存在。

Java 允许程序员为他的类定义相等集;如果他不想这样做,他可以简单地选择不覆盖equalshashCode并且最终得到您建议的语义。

举一个具体的例子,根据您的提议,这将在地图中创建两个单独的条目:

Map<Integer, String> map = new HashMap<>();
map.put(10_000, "a");
map.put(10_000, "a");

那是因为文字 10_000 每次都会被自动装箱到 的新实例中Integer,根据您的语义,它是两个单独的键。然后,声明

System.out.println(map.get(10_000));

会打印null,因为您当然是使用第三个键来获取。事实上,通过键检索任何地图值是不可能的。

于 2013-08-03T11:10:32.683 回答
4

==从面向对象的意义上说,这并没有多大意义。

new Integer(3)并且应该被认为是平等的new Integer(3)new Integer(2+1)其他一切都令人困惑,这就是equals描述。如果没有这个,当您不再拥有对原始键的引用时,就不可能从 HashMap() 中提取任何内容。当根据数据库中的数据将内容放入 HashMap 时,使用来自用户的输入在 HashMap 中查找内容也是不可能的。

如果您正在寻找周围的问题,==那么这应该意味着“等于”并且引用完整性应该有一些没有人真正知道的晦涩的句柄,因为您总是从不使用它。顺便说一句,这正是其他语言(例如 Scala)所做的。equalshashCode==

于 2013-08-03T11:20:24.983 回答
2

因为“==”用于比较2个对象的引用和内容.equals()。使用Java Collection JFrame时的一个重要规则是覆盖equals方法,并且.hashCode()如果您有2个具有相同内容的对象要映射到相同的密钥(哈希码)。如果您不覆盖 .enquals ,则调用的方法将来自 Object 类,该类将引用与“==”进行比较。覆盖 The 时的一个重要细节.hashCode()是使用最终字段。

于 2013-08-03T11:11:48.593 回答
2

在 java 中 == 用于检查引用相等性,而不是 equals() 和 hashCode() 作为对象相等性的“单一概念”一起工作。
如果您需要与 == 一起使用的 Map ,请使用IdentityHashMap

于 2013-08-03T11:13:28.430 回答
2

键是对象类型的,所有的类都是从Object类派生的。如果您正在使用您编写的类的键并且您没有在您的类中覆盖 equals 方法,会发生什么?这是答案:

无论您的类的两个对象是否具有完全相同的属性值,但 equals 的结果仍然是 false。仅仅因为默认等于 impelemtations 将检查两个对象是否指向相同的内存位置。这正是 == 比较所做的。

现在来讨论 equals 而不是 == 的 hashMap 用法。这是因为当您尝试将键放入映射时,JVM 会尝试检查两个对象是否相等。JVM 检查这种相等性的唯一智能是使用 equals 方法。并且使用其默认实现,它将执行 == 比较将执行的操作。但正如我上面提到的,如果两个对象具有相同的属性,它们实际上是相等的。但可悲的是 == 比较无法进行属性比较并得出真正的价值。因此覆盖 equals 方法或使用 equals 方法在逻辑上很重要,同时将值存储在 Map 中。

于 2013-08-03T11:14:05.210 回答