Java Hashcode和Equals实现

Java Hashcode和Equals实现,java,hash,hashmap,Java,Hash,Hashmap,考虑以下HashMap实现 HashMap<String,String> hashMap=new HashMap<>(); hashMap.put(new String("ABC"), "Hello"); hashMap.put("ABC", "Hello"); System.out.println(hashMap.size()); HashMap HashMap=newhashmap(); put(新字符串(“ABC”),“Hello”); hashMap.put(“

考虑以下
HashMap
实现

HashMap<String,String> hashMap=new HashMap<>();
hashMap.put(new String("ABC"), "Hello");
hashMap.put("ABC", "Hello");
System.out.println(hashMap.size());
HashMap HashMap=newhashmap();
put(新字符串(“ABC”),“Hello”);
hashMap.put(“ABC”,“Hello”);
System.out.println(hashMap.size());
代码如何将
size
返回为1,以及如何对其进行内部评估?但是,如果我使用
StringBuffer
而不是
String
code,则返回值为2。
这背后的原因是什么?

您在
HashMap HashMap=new HashMap()中缺少类型。如果要创建
String、String
的映射,则无法创建
StringBuilder
的对象作为键。如果您想同时支持这两种方法,那么可以使用
对象
而不是
字符串
作为键。 如果您想支持
String
StringBuilder
,那么您的代码将

HashMap<Object,String> hashMap=new HashMap<Object, String>();
HashMap HashMap=newhashmap();
以下是尺寸差异的解释


“任意值”被视为
String
类的实例<代码>字符串生成器
字符串
不同。在代码中,同一类的对象被创建为键,这会产生相同的hashCode(请参见
String.java
中的
hashCode()
函数)。但是,
StringBuilder
使用了Object.java中的
hashCode()。因此,它们具有不同的hashCode,并进行相应的处理。

HashMap
s使用
hashCode
方法确定bucket,然后
equals
确定是否有任何现有对象与要添加的对象相同。在您的情况下,
“ABC”
新字符串(“ABC”)
都将具有相同的
hashCode
,并将被
字符串视为相等。因此这两个对象将被视为相同


如果你不希望这样,那么你可以考虑使用对象引用来比较相等性。

HasMead使用<代码>对象。等值(其他)< /代码>作为2个对象是否应该被计算为“相同”的最终仲裁器。对于字符串,

equals
有效地比较字符串的字符内容,因此
“ABC”.equals(新字符串(“ABC”)
将返回
true

另一方面,StringBuffer使用对象的默认实现
equals
,它基本上检查两个对象是否引用相同(即,它们都指向完全相同的内存地址-这是
=
对java中的对象所做的)。由两个不同的
new
语句构造的两个StringBuffers引用永远不会相同,因此
也永远不会相等。这有很好的理由:大多数情况下,我们希望对象的
equals
方法对给定参数返回相同的答案,无论何时调用它。由于StringBuffer的内容可以被操作,所以两个缓冲区在一个时间点上可能具有相同的内容,但随后在其中一个缓冲区被附加到另一个缓冲区后,可能具有不同的内容

StringBuffer是可变的,这一事实可能使它不适合用作映射的键。除非您拥有与原始
放置的完全相同的StringBuffer,否则无法在地图上执行查找。相反,如果出于某种原因这种行为是您想要的,那么您可以使用,它将始终使用对象的内存地址来确定它是否与另一个对象相等,而不管其类型如何。不过,在使用带有字符串键的IdentityHashMap时要小心——因为,在代码中不同位置构造的两个等价字符串(从文字)实际上将指向同一块内存,因此引用将是相同的。

HashMap的put(K key,V value)方法首先通过key.hashCode()对bucket进行哈希运算%然后遍历Map.Entry对象的单链表来识别它 该键通过key.equals(k)存在。如果它找到一个键,它将更新该项的值,否则它将在链表的前面插入该键

1) 用于StringBuffer案例

    (i) new StringBuffer("ABC").equals(new StringBuffer("ABC")) is false
   (ii) new StringBuffer("ABC")!=new StringBuffer("ABC").hashCode() is false
这是因为StringBuffer不会覆盖并使用对象equals(Object o)和hashCode()。 因此,它们是地图中的两个不同条目

2) 字符串大小写

  (i) "ABC".equals(new String("ABC")) is true
 (ii) "ABC".hashCode()==new String("ABC").hashCode() is true

所以这两个是映射中的一个条目

我想你需要理解什么是hashmap, 用于从分配的内存位置存储和检索对象的Equal和hashcode。 因此,在您的示例中,密钥是通过内容验证的,而不是通过keyObjects引用验证的,因为它是字符串。即使您创建String=“ABC”文字或新字符串(“ABC”); Equals方法在本例中结果为true,因此现有键将替换为新键。这是集合的一个基本概念。HashMap使用SET作为键。因此,当我们尝试添加匹配的新密钥时,将使用equals方法替换现有密钥。 因此,我们应该正确地重写equals和hashcode方法。 规则: 如果两个对象相等,则它们必须具有相同的哈希代码。
如果两个对象具有相同的哈希代码,则它们可能相等,也可能不相等。

HashMap
首先使用对象的
hashCode()
,然后
equals()
进行比较。如果
hashCode
方法相等,
equals
方法返回true。当我打印要放入映射中的两个键的hashcode时,它们是相等的,这说明它们将存储在同一个bucket中,并将计算.equals。但是现在我有一个问题,当我使用不同的字符串初始化方法时,hashcode的计算结果如何相同。请尝试
newstring(“ABC”).equals(“ABC”)
newstringbuffer(“ABC”)。equals(“ABC”)
-第一条语句应该返回true,而第二条语句则返回false。这个问题的标题是“Hasmap实现”,但实际上,您的问题是关于
java.util.HashMap中的
equals()
hascode()
实现<