为什么hashmap在这里不返回null

时间:2015-08-06 14:29:48

标签: java hashmap

你好我正在攻读OCP考试,我对哈希图有疑问。在这里,我已经用(thirdStudent,“3”)替换了我的第一个键值(firstStudent,“1”)

package hashmapexam;

import java.util.HashMap;
import java.util.Map;

public class HashMapExam {

    public static void main(String[] args) {
        Student firstStudent = new Student("Rob");
        Student secondStudent = new Student("Catlin");
        Student thirdStudent = new Student("Rob");

        Map <Student,String> students = new HashMap<>();

        students.put(firstStudent, "1");
        students.put(secondStudent, "2");
        students.put(thirdStudent, "3");

        System.out.println("Size of the Map : " + students.size());

        System.out.println(students.get(firstStudent));
        System.out.println(students.get(secondStudent));
        System.out.println(students.get(thirdStudent));
    }
}
package hashmapexam;

class Student{

    String name;

    public Student(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    @Override
    public boolean equals(Object o){
        if(o instanceof Student && ((Student)o).getName().equals(this.getName())){
            return true;
        }
        else{
            return false;
        }
    }

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

我得到以下输出

  

地图的大小:2

     

3

     

2

     

3

似乎它们已被正确替换,因为地图的大小是2.但是如何使用firstStudent和thirdStudent Keys检索值“3”?没有firstStudent键被第三学生取代?

7 个答案:

答案 0 :(得分:2)

firstStudentthirdStudentequal。这意味着您可以使用任一引用作为键来获取相应的值。

顺便说一句,使用length的{​​{1}}对于String方法来说不是一个好主意,因为它会导致许多不同的通用名称具有相同的hashCode }。最好使用hashCode的{​​{1}}。

答案 1 :(得分:1)

因为哈希映射(如名称所示)使用键的哈希值将值放入其桶中。在您的情况下,您的Student类实现了equalshashcode方法,其中firstStudentthirdStudent都返回相同的哈希值;因此,您的地图中有2个值,并且检索(firstStudentthirdStudent)将返回相同的值; 3,因为thirdStudent替换1设置的值firstStudent,因为它们都具有相同的哈希值(编辑)并且被视为相等

更新

students.put(firstStudent, "1");
// map size: 1
students.put(secondStudent, "2");
// map size: 2
students.put(thirdStudent, "3");
// map size: 2 (replaced first inserted value)

本质上

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

答案 2 :(得分:1)

您的equals()方法表示具有相同Student的任何name实例都相同。 HashMap在其操作中使用此相等,所以

students.put(thirdStudent, "3");

将替换

创建的条目
students.put(firstStudent, "1");

thirdStudentfirstStudent是等效键。

同样,students.get(firstStudent)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可以用作HashMap s中的键的原因。

答案 3 :(得分:1)

您的Student firstStudentthirdStudent对象相等 hashCode 也会返回相同的值,即3因为覆盖学生班中的hashCode,实习生返回字符串的长度,即

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

答案 4 :(得分:1)

在hashmap的put方法中

  

如果地图以前包含该键的映射,则为旧值   由指定的值替换。 据说地图m包含一个   当且仅当map.containsKey(key)返回时才映射键k   真正。当且仅当此映射包含键k的映射使得key == null时,map.containsKey(key)才返回true。 k == null:key.equals(k)

在你的情况下,你首先添加&#34; firstStudent&#34;有价值&#34; 1&#34;而且你已经添加了&#34; thirdStudent&#34;但作为thirdStudent.equals(firstStudent),firstStudent的值将被&#34; 3&#34;

取代 在hashmap的get方法中

  

返回指定键映射到的值,如果是,则返回null   此映射不包含键的映射。更正式的是, 如果这样的话   map包含从键k到值v的映射,使得(key == null   ? k == null:key.equals(k)),然后此方法返回v;否则它   返回null。

在您的情况下,firstStudent和thirdStudent引用相同的值

答案 5 :(得分:0)

students.put(firstStudent,“1”);

地图: Rob - &gt; 1

students.put(secondStudent, "2");

地图: Rob - &gt; 1 和        Catlin - &gt; 2

students.put(thirdStudent, "3");        

地图: Rob - &gt; 3 (第三名学生也被命名为'Rob')        Catlin - &gt; 2

因此,如果您使用'Rob'访问Map,则获得'3',因为第二个Put使用'Rob'将值'1'替换为'3'。自从第一次和 第三个学生都被称为'Rob',equals只按名称进行比较,两者都有相同的哈希码,从HashMap的角度看它们是相同的键。 因此,在三次“放置”操作后,地图只包含两个条目。

所以你得到Rob - &gt; 3 Catlin - &gt; 2 Rob - &gt; 3 ...序列3,2,3

答案 6 :(得分:0)

错误:href="#{{ loc }}" firstStudent是同一个对象。

&#34;同样的&#34;意味着它们在java方面是相同的。

原因:内容相同的字符串与您的学生相同 被称为&#34;抢&#34;。

您的hashMap将两个学生放在同一个桶中,因为名称(=键)相等,因此两者都为您提供输出thirdStudent