向HashSet中添加完对象后,在修改对象,未进行去重 ,不知是什么原因,请大佬指正
  RuXuq8CpAyRj 2023年12月07日 81 0


项目场景:

今天在项目中向利用hashset给自定义实体类进行去重,但是去重未成功, 项目中加的@Data注解现在依然未解决,看网上文章有感,so写下了此文章,文章有不足之处,希望各位大佬指正


问题描述

 伪代码

/**
 * 自定义实体类
 * @Description:
 * @Date Created in 2022-10-11-20:05
 * @Modified By:
 */
public class Stu {
    private String name;
    private Integer age;

    public Stu(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Stu{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append('}');
        return sb.toString();
    }
}
/**
 * 测试类
 * @Description:
 * @Date Created in 2022-10-11-20:06
 * @Modified By:
 */
public class StuTest {
    public static void main(String[] args) {
        Stu s1 = new Stu("大大王", 100);
        Stu s2 = new Stu("大大王", 100);
        Stu s3 = new Stu("大大王11", 3);
        HashSet<Stu> students = new HashSet<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        System.out.println(students);
    }
}

 输出结果:

向HashSet中添加完对象后,在修改对象,未进行去重 ,不知是什么原因,请大佬指正_开发语言


原因分析:

HashSet 的 add方法使用的是 hashcode 和equals进行比较

需要重写hashcode 和equals

public class Stu {
    private String name;
    private Integer age;

    public Stu(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Stu{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append('}');
        return sb.toString();
    }

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

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
/**
 * @Description:
 * @Date Created in 2022-10-11-20:06
 * @Modified By:
 *
 *    使用HashSet存储自定义对象并遍历
 *    通过查看源码发现:
 *                HashSet的add()方法,首先会使用当前集合中的每一个元素和新添加的元素进行hash值比较,
 *                如果hash值不一样,则直接添加新的元素
 *                如果hash值一样,比较地址值或者使用equals方法进行比较
 *                比较结果一样,则认为是重复不添加
 *                所有的比较结果都不一样则添加
 */
public class StuTest {
    public static void main(String[] args) {
        Stu s1 = new Stu("大大王", 100);
        Stu s2 = new Stu("大大王", 100);
        Stu s3 = new Stu("大大王11", 3);
        HashSet<Stu> students = new HashSet<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        System.out.println(students);
    }
}

 重写hashcode 和equals,再次进行测试

 去重成功

向HashSet中添加完对象后,在修改对象,未进行去重 ,不知是什么原因,请大佬指正_i++_02

10月23日补充

向set中添加完对象后,在修改对象,未进行去重 ,不知是什么原因????

欢迎各位大佬指正

直接上代码

ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("zhengsan", 12));
        students.add(new Student("lisi", 15));
        students.add(new Student("wangwu", 20));
        HashSet<Student> studentHashSet = new HashSet<>();
        for (Student student : students) {
            for (int i = 0; i < 2; i++) {
                studentHashSet.add(student);
                student.setName("张三");
            }
        }

        for (Student s : studentHashSet) {
            System.out.println(s);
        }

输出结果

向HashSet中添加完对象后,在修改对象,未进行去重 ,不知是什么原因,请大佬指正_System_03

将数据放入list中,比较hashcode和equal看它是否相同

ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("zhengsan", 12));
        students.add(new Student("lisi", 15));
        students.add(new Student("wangwu", 20));

        HashSet<Student> studentHashSet = new HashSet<>();
        for (Student student : students) {
            for (int i = 0; i < 2; i++) {
                studentHashSet.add(student);
                student.setName("张三");
            }
        }
        ArrayList<Student> list = new ArrayList<>();
        for (Student s : studentHashSet) {
            System.out.println(System.identityHashCode(s) + "," + s);
            list.add(s);
        }
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(0) + "  " + list.get(4));
            System.out.println("hashcode:" + (list.get(0) == (list.get(4))));
            System.out.println("equal:" + list.get(0).equals(list.get(4)));
        }

 

向HashSet中添加完对象后,在修改对象,未进行去重 ,不知是什么原因,请大佬指正_开发语言_04

 hashcode和equal是相同的,但是没有去重,很是头大。

23年5月25日 破案啦

将上面的代码改变一下,调整一下setName的位置,并打印hashcode

ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("zhengsan", 12));
        students.add(new Student("lisi", 15));
        students.add(new Student("wangwu", 20));
        HashSet<Student> studentHashSet = new HashSet<>();
        for (Student student : students) {
            for (int i = 0; i < 2; i++) {
                System.out.println(student.hashCode());
                studentHashSet.add(student);
                student.setName("张三");
            }
        }

        for (Student s : studentHashSet) {
            //System.out.println(s + "hashcode="+ s.hashCode());
            System.out.println(s);
        }

输出结果:

-1318086619
776222
3323429
776315
-795135410
776470
Student{name='张三', age=15}
Student{name='张三', age=12}
Student{name='张三', age=20}
Student{name='张三', age=15}
Student{name='张三', age=12}
Student{name='张三', age=20}

Process finished with exit code 0

可以看到向set集合中添加的元素的hashcode都是不一样的,set集合是根据hashcode和equal的值是否相同进行去重的,hashcode不一样,当然不可以去重。

继续改变一下setName的位置,看一下效果

ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("zhengsan", 12));
        students.add(new Student("lisi", 15));
        students.add(new Student("wangwu", 20));
        HashSet<Student> studentHashSet = new HashSet<>();
        for (Student student : students) {
            for (int i = 0; i < 2; i++) {
                student.setName("张三");
                System.out.println(student.hashCode());
                studentHashSet.add(student);
            }
        }

        for (Student s : studentHashSet) {
            //System.out.println(s + "hashcode="+ s.hashCode());
            System.out.println(s);
        }

输出结果

776222
776222
776315
776315
776470
776470
Student{name='张三', age=15}
Student{name='张三', age=12}
Student{name='张三', age=20}

可见已经去重了,hashcode值也一样

无法去重的原因:

其实很简单,第一次向set集合中存储数据,第二次使用setName改变了Student对象的值,所以当然不能去重。  使用双重循环,添加数据的时候一定要注意这个问题!!!

完结

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月07日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   53   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   109   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
RuXuq8CpAyRj