【问题标题】:Duplicate value exception in SetSet中的重复值异常
【发布时间】:2011-06-24 06:06:04
【问题描述】:

据说那些实现 Set 接口的结构不允许重复元素。我只是想知道,他们所说的重复是什么意思?在值方面重复?或者就对象而言。例如,我可以添加两个相同值的 Integer 对象。我还可以添加两次相同的对象。他们所说的重复是什么意思?什么时候会抛出异常?

【问题讨论】:

    标签: java collections


    【解决方案1】:

    重复的意思是在另一篇帖子a.equals(b) 中解释,这意味着a.hashCode()==b.hashCode()。 但是,当你添加重复元素时,不会有任何异常,只是不会被添加两次。

    【讨论】:

      【解决方案2】:

      相等的定义取决于容器。 通常是 .equals()/.hashCode() 关系,但也有一些容器使用身份来表示相等。

      【讨论】:

      • 不完全一样,相等的定义是在Set接口中指定的。 “更正式地说,集合不包含一对元素 e1 和 e2 使得 e1.equals(e2),并且最多包含一个空元素”
      • 有一个叫做 IdentityHashSet 的东西,类似于 java.util.IdentityHashMap——文档说“这个类不是通用的 Map 实现!虽然这个类实现了 Map 接口,它故意违反了 Map 的一般合同,该合同要求在比较对象时使用 equals 方法。此类仅在需要引用相等语义的极少数情况下使用。用 Set 代替 Map,你会看到我在哪里......
      • 我非常了解这些收藏;我的意思是提到“破坏” Set 合同的实现并不是一个很好的例子。由于 OP 的问题明确提到了“设置接口”,equals() 在这里是一个更合适的答案。当然,YMMV。
      【解决方案3】:

      java.util 集合中,重复意味着a.equals(b) 并且应该 暗示a.hashcode()==b.hashcode()

      【讨论】:

      • 必须暗示哈希码相等,如 Object.hashCode() 中所指定。
      • @EJP - 嗯,“必须”的意思是“如果你不这样做,你会非常抱歉。”
      • @EJP - 如果这里没有什么好争论的,那你为什么要争论呢? 事实上,即使在 Java 系统库中,也有一些类违反了您所依赖的约定。
      • @Malvolio 我不“依赖”任何“合同”。我知道世界上并非所有事物都符合要求。我只是在重复 Javadoc 所说的话。它说“必须”。
      【解决方案4】:

      根据 Javadocs;这意味着e1.equals(e2) 返回 true 的任何两个元素都被视为重复元素。不同的集合实现使用不同的策略来存储元素; HashSet 使用对象的hashCode,而TreeSet 依赖于自然排序(Comparable 接口)或自定义Comparator

      【讨论】:

        【解决方案5】:

        Fiver 和 Alvin 给出了很好的答案,因为“aps”表示他可以添加两个相同的整数和对象,但不会出现任何编译器错误或运行时异常,这是真的。

        如果你像你说的那样添加这些对象,然后像这样运行一些代码

        System.out.println(theSetYouMade.size());
        

        然后您会看到它没有添加您所说的那些重复项。

        【讨论】:

        • 嘿,我真的不是那个意思...我只是说有两种添加重复项的方法...我没有谈论它们是否会产生编译器错误... .反正我明白了...
        【解决方案6】:

        obj1obj2 的副本,如果 obj1.equals(obj2) 返回 true。所以你可以看到,equal的定义实际上取决于equals的实现。

        你可以写一个集合,比如 DistincObjectSet 其中重复的意思是obj1==obj2

        另一个例子是你可以有 EmployeeSet,其中重复意味着 obj1.employeeNo == obj2.employeeNo,在这种情况下,你应该覆盖 Employee 类中的 equals() 方法来比较员工编号。

        Set API 的设计表明您尝试添加重复元素,add() 方法应该返回 false 而不是抛出异常。

        【讨论】:

        • 所以这取决于集合的类型,对吧? TreeSet 或 HashSet 或一些自定义 Set 等?
        • obj1.hashCode()==obj2.hashCode() 并不暗示 obj1.equals(obj2)
        • "对于 HashSet,如果两个对象具有相同的哈希码,则它们是相等的"。这是不正确的。如果 equals() 返回 true,则两个对象相等。期间。
        • @EJP,是的,我的说法是错误的。感谢您指出了这一点。我已经相应地修改了我的答案
        • @EJP 以及 .equals() 是如何在 HashSet 中实现的?我的意思是如何在任何集合中比较自定义对象?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-04
        • 2023-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-04
        • 1970-01-01
        相关资源
        最近更新 更多