由一道关于hashSet与hashMap底层实现的面试题

题目

public class TestPerson {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person(1001, "AAA");
        Person p2 = new Person(1002, "BBB");

        set.add(p1);
        set.add(p2);
        p1.name = "CCC";
        set.remove(p1);
        System.out.println(set);

        set.add(new Person(1001,"CC"));
        System.out.println(set);

        set.add(new Person(1001,"AAA"));
        System.out.println(set);
    }
}

其中Person类重写了hashCode、equals、和toString方法

public class Person {
    int age;
    String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

问输出结果是多少?


分析

答题前我们首先要知道:
HashSet和HashMap都是由数组+链表+红黑树实现。(JDK1.8后)

HashSet和HashMap存储过程:
1.根据key的hash值计算位置,如果这个位置没有元素,则直接添加。
2.如果这个位置有元素,再比较hash值,如果hash值不同,则形成链表。
3.如果hash值相同,再比较equals方法,如果equals方法为false,则形成链表,如果为true,则认为是重复元素,不再添加。
位置相同,hash值相同,equals为true同时成立才认为是重复元素。

HashSet和HashMap删除过程:
同理要位置相同,hash值相同,equals为true同时成立才认为是重复元素,才能删除。

回到题目
set.add(p1)、set.add(p2): set首先添加p1(1001,“AAA”)、p2(1002,“BBB”)对象后,将p1对象的name值改变了(1001,“CCC”),此时虽然set中p1的属性值为(1001,“CCC”),但其数组位置是按照(1001,“AAA”)计算的。
set.remove(p1): 此时位置是按照更改后的(1000,“CCC”)计算的,与set中存储的p1的位置不同,故认为set中没有与之重复的元素,不删除。
set.add(new Person(1001,“CC”)): 理由同上,此时按照更改后的属性计算的位置与原本计算的位置不同,故认为set中没有与之重复的元素,于是将其添加进数组。
set.add(new Person(1001,“AAA”)): 属性与p1原属性相同,按照此属性计算的位置与p1在数组中存储的位置相同,于是再比较hash值,hash值不同(重写了hashCode函数,属性相同hash相同,属性不同hash不同。当然,不重写hashCode函数两者hash值也不同)。故认为两者不是重复元素,将新对象添加再p1后形成链表。
综上,这道题最后的答案是:由一道关于hashSet与hashMap底层实现的面试题

上一篇:修改用户uid


下一篇:位运算符