为什么Java使用’equals’代替’==’来检查对象在Map中的存在?
假设我想将一个键及其值放在Map中。
我相信这是Java的作用:
-
获取密钥的Hashcode并检查映射中是否存在具有相同哈希码的密钥。
-
如果没有具有相同Hashcode的密钥,则可以将密钥放入Map中。
-
如果存在具有相同Hashcode的密钥,则使用equals来确定密钥是否可以放入Map中。
我的问题是为什么在这个过程中不使用==
而不是equals
?
做你的建议将打破equals
/ hashCode
串联的整个概念。 equals
和hashCode
都将变得无用,甚至不应该存在。
Java允许程序员为他的类定义相等集; 如果他不想这样做,他可以简单地选择不使用覆盖的equals
和hashCode
– 并最终确定你提出的语义。
举一个具体的例子,根据你的提议,这将在地图中创建两个单独的条目:
Map 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中查找内容也是不可能的。
如果您正在寻找==
, equals
和hashCode
周围的问题,那么==
应该真正意味着“等于”,并且参照完整性应该有一些模糊的句柄,没有人真正知道,因为你总是从不使用它。 顺便说一句,这正是Scala所做的其他语言。
在java中,==用于检查引用相等性,而equals()和hashCode()一起作为对象相等的“单一概念” 。
如果您需要使用==使用IdentityHashMap的Map。
键是对象类型,所有类都是从Object类中派生出来的。 如果您正在使用由您编写的类的键,并且您没有在类中重写equals方法,那么会发生什么? 这是答案:
无论您的类中的两个对象是否具有完全相同的属性值,但仍然是equals的结果将为false。 仅仅因为默认等于impelemtations将检查两个对象是否指向相同的内存位置。 这正是==比较所做的。
现在来到hashals使用equals而不是==。 这是因为当您尝试将键放入映射时,JVM会尝试检查两个对象是否相等。 JVM检查此相等性的唯一智能是使用equals方法。 并且通过其默认实现,它将执行== comparision将执行的操作。 但正如我上面提到的,如果两个对象具有相同的属性,它们实际上是相等的。 但遗憾的是==比较不能进行属性比较并提出真正的价值。 因此,重写equals方法或使用equals方法在逻辑上非常重要,同时将值存储在Map中。
因为“==”用于比较2个对象的引用和.equals()
的内容。使用Java Collection JFrame时的一个重要规则是覆盖equals方法,还有.hashCode()
这样如果你有2个对象具有相同的内容以映射在相同的密钥(哈希码)。 如果不覆盖.enquals,则调用的方法将来自Object类,该类将引用与“==”进行比较。覆盖.hashCode()
时的一个重要细节是使用final字段。