我来变强了 2024-07-28 15:36 采纳率: 100%
浏览 8
已结题

关于#java#的问题:HashSet不允许重复值,但修改后再添加一个一样的就可以?

HashSet不允许重复值,为什么修改后再添加一个一样的就可以。代码输出

img

代码

@Test
    public void test2() {
        HashSet<UserPojo> set = new HashSet<>();
        UserPojo p1 = new UserPojo("AA", 1001);

        set.add(p1);
        p1.setName("CC");
        set.remove(p1);
        /*在调用 set.remove(p1) 时,并不会删除原先的 p1,这是因为 HashSet 在执行 remove 操作时,会根据对象的 hashCode 和 equals 方法
        来判断对象的唯一性和是否存在的。当你修改了对象的属性(比如 p1.name = "CC"),这可能会导致对象的 hashCode 改变,因此 HashSet 在内部
        寻找该对象时会用新的 hashCode 进行查找,导致可能找不到原始的对象。*/
        UserPojo p3 = new UserPojo("CC",1001);
        set.add(p3);
        UserPojo p4 = new UserPojo("AA",1001);
        set.add(p4);
        System.out.println(set);
        System.out.println(p1.hashCode()==p3.hashCode());
        System.out.println(p3.equals(p1));
        System.out.println(p4.hashCode());
    }
    static class UserPojo {
        private String name;
        private int age;

        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

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

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

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

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof UserPojo userPojo)) return false;
            return getAge() == userPojo.getAge() && Objects.equals(getName(), userPojo.getName());
        }

        @Override
        public int hashCode() {
            return Objects.hash(getName(), getAge());
        }
    }

  • 写回答

1条回答 默认 最新

  • 专家-司宇[在线] 2024-07-28 15:36
    关注

    引自免费微信小程序:皆我百晓生

    这个测试的关键在于 HashSet 中元素的唯一性是通过元素的 hashCode()equals() 方法来决定的。当你在 HashSet 中添加对象时,Java 使用对象的 hashCode() 方法来决定对象在内部数据结构中的位置。如果两个对象具有相同的 hashCode() 值并且它们的 equals() 方法返回 true,那么它们被视为相同的对象。这就是 HashSet 不允许重复值的原因。

    然而,当你修改一个对象的属性(例如 name),这可能会导致对象的 hashCode() 改变。这是因为 hashCode() 方法是基于对象的属性值来计算的。在这种情况下,即使两个对象看起来是相同的(因为它们可能有相同的 nameage 属性),但由于他们的 hashCode() 可能不同,它们将被视为不同的对象。这就是为什么你可以在修改一个对象的属性后再向 HashSet 添加一个看似相同的对象,它仍然会被接受的原因。这是因为新的对象在 HashSet 中有了一个新的独特的 hashCode() 值。

    你的测试代码中的输出也反映了这一点:当你修改 p1name 属性并添加新的 UserPojo 对象 p3p4HashSet 时,虽然 p1p3 的属性值相同,但他们的 hashCode() 不同,所以他们在 HashSet 中被视为不同的对象。这就是为什么你的输出中包含了三个不同的 UserPojo 对象的原因。同时,由于 p3p4hashCode() 相同(假设他们的属性值不同但计算出的哈希值相同),它们在 HashSet 中被视为同一个对象(如果存在哈希冲突,实际表现可能不同)。但这通常不会发生,除非特意设计了哈希碰撞的情况。这就是你看到输出的哈希值相同的原因。实际上这种情况的碰撞在实际开发中是非常罕见的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 8月19日
  • 已采纳回答 8月11日
  • 创建了问题 7月28日