专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

这绝对是我见过最坑的一道笔试题,没有之一

这是我见过的最容易出错的一道Java笔试题,如果不是对Set有非常深入的理解,百分百会出错。

下面就来看一下,这道题到底坑在哪里。

题目如下:

定义了一个Person类,重写了hashCode和equals方法,如下图所示:

public class Person {    public int id;    public String name;    public Person(int id, String name) {        this.id = id;        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;        if (id != person.id) return false;        return name != null ? name.equals(person.name) : person.name == null;    }    @Override    public int hashCode() {        int result = id;        result = 31 * result + (name != null ? name.hashCode() : 0);        return result;    }    @Override    public String toString() {        return "Person{" +                "id=" + id +                ", name='" + name + '\'' +                '}';    }}

请写出下面一段代码的运行结果

public class Test {    public static void main(String[] args) {        HashSet set = new HashSet();        Person p1 = new Person(1001,"AA");        Person p2 = new Person(1002,"BB");        set.add(p1);        set.add(p2);        p1.name = "CC";        set.remove(p1);        System.out.println(set);    }}

此时的运行结果是怎样的呢?可以先自己猜一下,然后在看运行结果。

此时的输出结果如下所示:

136_1.png

为什么是这样的运行结果呢?

因为存储p1时,是按照p1的哈希值计算的索引位置,之后p1.name进行了修改,那么当删除p1时,会按照现在的p1,也就是name修改后的p1的哈希值计算的索引,此时计算出的索引位置与之前存储p1的索引位置不相同,所以不会把p1删除掉。

那么接着往下看,还有更坑的。

public class Test {    public static void main(String[] args) {        HashSet set = new HashSet();        Person p1 = new Person(1001,"AA");        Person p2 = new Person(1002,"BB");        set.add(p1);        set.add(p2);        p1.name = "CC";        set.remove(p1);        System.out.println(set);        set.add(new Person(1001,"CC"));        Sys,,idtem.out.println(set);    }}

此时的运行结果又是怎样的呢?Person(1001,“CC”)能存储成功吗?可以先自己猜一下,再看运行结果。

此时的运行结果如下所示:

136_2.png

那么为什么是这样的运行结果呢?

因为存储p1时,是按照第一次的哈希值计算的索引位置,也就是按照p1=new Person(1001,“AA”)计算出来的索引位置进行的存储。后来又把name值进行了修改,那么此时p1的id=1001,name=“CC”。当又往Set中添加id=1001,name=”CC”的Person时,会按照Person(1001,“CC”)的哈希值计算索引位置,此时计算出的索引位置与之前存储p1时id=1001,name=”AA”计算的索引位置不一样,所以可以添加成功。

别急,还有更坑的,接着往下看。

public class Test {    public static void main(String[] args) {        HashSet set = new HashSet();        Person p1 = new Person(1001,"AA");        Person p2 = new Person(1002,"BB");        set.add(p1);        set.add(p2);        p1.name = "CC";        set.remove(p1);        System.out.println(set);        set.add(new Person(1001,"CC"));        System.out.println(set);                set.add(new Person(1001,"AA"));        System.out.println(set);    }}

此时的运行结果又是怎样的呢?当Person(1001,“AA”)再次存储时,到底能不能存储成功呢?

此时的运行结果如下所示:

136_3.png

那么为什么是这样的运行结果呢?

因为当再次存储id=1001,name=”AA”的Person时,虽然使用哈希值计算出的索引位置相同,但是因为此时p1的name值为CC,当调用equals方法判断两者是否相等时,会返回false,所以可以存储成功。

注意:Set集合是元素无序、不可重复的集合,如果是把两个相同的元素加入同一个Set 集合中,则添加操作失败。

向HashSet中添加元素的过程:

当向HashSet集合中存入一个元素时,HashSet会先计算出该元素的哈希值,然后把哈希值与数组长度-1进行与运算计算出该元素在HashSet底层数组中的存储位置。然后判断该位置上是否已经存在元素,如果不存在则直接存储成功;如果该位置上已经存在一个或多个元素,那么就会从前往后依次比较元素是否相等。比较时会先比较元素的哈希值,如果哈希值不相同则添加成功。如果哈希值相同则会调用元素所在类的equals方法进行比较;如果equals方法返回true,则表示两者相等,添加失败;如果equals方法返回false,则表示两者不相等,会添加成功。

文章永久链接:https://tech.souyunku.com/29337

未经允许不得转载:搜云库技术团队 » 这绝对是我见过最坑的一道笔试题,没有之一

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们