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()
实现<