假设我想把一个键和它的值放在一个 Map 中。
我相信这是 Java 所做的:
获取key的Hashcode,查看map中是否有相同hashcode的key。
如果没有具有相同 Hashcode 的键,则可以将键放入 Map。
如果有一个具有相同 Hashcode 的键,则使用 equals 来确定该键是否可以放入 Map 中。
我的问题是为什么不在这个过程中使用==
而不是equals
?
做你建议的事情会打破equals
/hashCode
串联的整个概念。两者equals
和hashCode
都会变得无用,甚至不应该存在。
Java 允许程序员为他的类定义相等集;如果他不想这样做,他可以简单地选择不覆盖equals
,hashCode
并且最终得到您建议的语义。
举一个具体的例子,根据您的提议,这将在地图中创建两个单独的条目:
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
,因为您当然是使用第三个键来获取。事实上,通过键检索任何地图值是不可能的。
==
从面向对象的意义上说,这并没有多大意义。
new Integer(3)
并且应该被认为是平等的new Integer(3)
。new Integer(2+1)
其他一切都令人困惑,这就是equals
描述。如果没有这个,当您不再拥有对原始键的引用时,就不可能从 HashMap() 中提取任何内容。当根据数据库中的数据将内容放入 HashMap 时,使用来自用户的输入在 HashMap 中查找内容也是不可能的。
如果您正在寻找周围的问题,==
那么这应该意味着“等于”并且引用完整性应该有一些没有人真正知道的晦涩的句柄,因为您总是从不使用它。顺便说一句,这正是其他语言(例如 Scala)所做的。equals
hashCode
==
因为“==”用于比较2个对象的引用和内容.equals()
。使用Java Collection JFrame时的一个重要规则是覆盖equals方法,并且.hashCode()
如果您有2个具有相同内容的对象要映射到相同的密钥(哈希码)。如果您不覆盖 .enquals ,则调用的方法将来自 Object 类,该类将引用与“==”进行比较。覆盖 The 时的一个重要细节.hashCode()
是使用最终字段。
在 java 中 == 用于检查引用相等性,而不是 equals() 和 hashCode() 作为对象相等性的“单一概念”一起工作。
如果您需要与 == 一起使用的 Map ,请使用IdentityHashMap。
键是对象类型的,所有的类都是从Object类派生的。如果您正在使用您编写的类的键并且您没有在您的类中覆盖 equals 方法,会发生什么?这是答案:
无论您的类的两个对象是否具有完全相同的属性值,但 equals 的结果仍然是 false。仅仅因为默认等于 impelemtations 将检查两个对象是否指向相同的内存位置。这正是 == 比较所做的。
现在来讨论 equals 而不是 == 的 hashMap 用法。这是因为当您尝试将键放入映射时,JVM 会尝试检查两个对象是否相等。JVM 检查这种相等性的唯一智能是使用 equals 方法。并且使用其默认实现,它将执行 == 比较将执行的操作。但正如我上面提到的,如果两个对象具有相同的属性,它们实际上是相等的。但可悲的是 == 比较无法进行属性比较并得出真正的价值。因此覆盖 equals 方法或使用 equals 方法在逻辑上很重要,同时将值存储在 Map 中。