Java 为什么hashmap没有';这里不能返回null

Java 为什么hashmap没有';这里不能返回null,java,hashmap,Java,Hashmap,你好,我正在为OCP考试学习,我对hashmaps有疑问。在这里,我将我的第一个键值(firstStudent,“1”)对替换为(thirdStudent,“3”) 我得到以下输出 地图大小:2 三, 二, 三, 因为地图的大小是2,所以它们似乎被正确地替换了。但是它如何使用firstStudent和thirdStudent键检索值“3”?第一个学生的钥匙不是被第三个学生代替了吗 因为散列映射(顾名思义)使用键的散列将值放入其存储桶中。在您的例子中,您的Student类实现了equals和has

你好,我正在为OCP考试学习,我对hashmaps有疑问。在这里,我将我的第一个键值(firstStudent,“1”)对替换为(thirdStudent,“3”)

我得到以下输出

地图大小:2

三,

二,

三,

因为地图的大小是2,所以它们似乎被正确地替换了。但是它如何使用firstStudent和thirdStudent键检索值“3”?第一个学生的钥匙不是被第三个学生代替了吗

因为散列映射(顾名思义)使用键的散列将值放入其存储桶中。在您的例子中,您的
Student
类实现了
equals
hashcode
方法,其中
firstststudent
thirdStudent
都返回相同的散列;因此,地图中有2个值,检索(
firstststudent
thirdStudent
)将返回相同的值
3
,因为
thirdStudent
替换了
firstststudent
设置的值
1
,因为它们都具有相同的散列值(edit),并且被认为是相等的

更新 本质上

boolean b = students.get(firstStudent).equals(students.get(thirdStudent));
// b==true since firstStudent.equals(thirdStudent)==true

第一名学生
第三名学生
是平等的。这意味着您可以使用任一引用作为键来获取相应的值

顺便说一下,对于
hashCode
方法来说,使用
字符串的
长度
是个糟糕的主意,因为它会导致许多不同的公共名称具有相同的
hashCode
。最好使用
字符串的
hashCode

students.put(firstststudent,“1”)

地图:Rob->1

地图:Rob->1Catlin->2

地图:Rob->3(第三个学生也被命名为“Rob”) Catlin->2

因此,如果您使用“Rob”访问地图,您将得到“3”,因为第二个Put用“Rob”替换了值“1”为“3”。自从第一次和第二次 第三个学生都被称为“Rob”,equals只按名称进行比较,并且都有相同的hashcode。从HashMap的角度来看,它们是相同的键因此,在三次“put”操作之后,映射只包含两个条目。

所以你得到了Rob->3 Catlin->2 Rob->3。。。序列3,2,3

您的
equals()
方法表示任何具有相同
名称的
学生
实例都是相等的
HashMap
在其操作中使用此等式,因此

students.put(thirdStudent, "3");
将替换由创建的条目

students.put(firstStudent, "1");
as
thirdStudent
firstStudent
是等效键

类似地,
students.get(firstststudent)
students.get(thirdStudent)
返回与所用键相同的值

(当然,对于散列数据结构,这取决于
hashCode
的正确实现)

另一个例子:

new Integer(1) != new Integer(1)
(new Integer(1)).equals(new Integer(1))
(new Integer(1)).hashcode() == (new Integer(1)).hashcode()

这就是为什么
Integer
s可以用作
HashMap
s中的键。

您的
Student
对象是
firstststudent
thirdStudent
相等的hashCode也会返回相同的值,即3,因为重写了
hashCode
在学生课堂上,实习生返回字符串的长度,即

@Override
public int hashCode(){
    return name.length();
}

hashmap的输入方法:

如果映射以前包含键的映射,则旧值 由指定的值替换称地图m包含 键k的映射当且仅当map.containsKey(键)返回 对。当且仅当此映射包含密钥k的映射,使得key==null时,and map.containsKey(key)返回true?k==null:key.equals(k)

在您的案例中,您首先添加了值为“1”的“firstStudent”,然后添加了“thirdStudent”,但作为thirdStudent.equals(firstStudent),因此firstStudent的值将替换为“3”

在hashmap的get方法中:

返回指定键映射到的值,如果为空,则返回null 此映射不包含密钥的映射。更正式地说,如果 映射包含从键k到值v的映射,使得(键==null ?k==null:key.equals(k)),则此方法返回v;否则它 返回空值。


在您的案例中,firstStudent和thirdStudent引用相同的值。错误:
firstStudent
thirdStudent
是相同的对象

“相同”意味着从java的角度来看,它们是平等的

原因:内容相同的字符串是平等的,你的学生也是平等的 都叫“罗布”


您的hashMap将两个学生放在同一个bucket中,因为名称(=键)是相等的,因此两者都给您输出
3

您应该得到地图的输出
大小:3
否我得到2:o尝试了几次times@Nitesh你为什么这么认为?@SotiriosDelimanolis我在我的机器上执行了相同的代码,它给出的大小为3@NiteshVirani你做错了。散列不能决定一个文件中的身份哈希映射。哈希上的冲突是完全允许的,也是正常的(否则,就不会只有存储桶和插槽)。op的问题在于
equals()
方法。不,他在问为什么
firstststudent
没有返回
null
。我已经解释了原因;因为
firstststudent
thirdStudent
都返回相同的散列,所以它们都访问相同的存储桶。@billc.cn我不是在争论冲突;映射中的值存储在数组中,其中值索引由其键的散列确定。我将不详细讨论这种实施的细节,但我只想说,这与OP的问题无关,我的回答没有错;从第一个学生和第三个学生出生起
students.put(thirdStudent, "3");        
students.put(thirdStudent, "3");
students.put(firstStudent, "1");
new Integer(1) != new Integer(1)
(new Integer(1)).equals(new Integer(1))
(new Integer(1)).hashcode() == (new Integer(1)).hashcode()
@Override
public int hashCode(){
    return name.length();
}