【问题标题】:Which problems can stem from overriding java.util.HashSets contains()-method?哪些问题可能源于覆盖 java.util.HashSets contains() 方法?
【发布时间】:2021-01-06 05:44:42
【问题描述】:

我想使用HashSet 来存储一些对象:

public class StoredObject{
    Type type; //Type is an enum
    //other fields

    Type getType(){return type;}
}

现在,我只想存储同一个Type 中的一个StoredObject,所以我在HashSet 的子类中覆盖contains()

public MySet<E extends StoredObject> extends java.util.HashSet<E>{
    @Override
    public boolean contains(Object o) {
        if(StoredObject.class.isAssignableFrom(o.getClass())) {//if o implements StoredObject
            for(StoredObject s : this) {
                if(s.getType() == ((StoredObject) o).getType()) return true;
            }
        }
        return false
    }
}

在此之前我想使用HashSet 并修改StoredObjectequals()。但是,上面的方法似乎是一种更短更安全的方法,尤其是在我的例子中,存储的对象都实现了一个接口并且不扩展同一个类。

现在我的问题是:这个实现安全吗?我试图寻找它可能会破坏的东西,但没有找到任何东西。我读到覆盖equals() 会破坏集合。 另外,这个子类是否违背了HashSet 的目的,因为它不使用HashMap 来代替contains()

【问题讨论】:

  • “这个子类是否违背了 HashSet 的目的”?——是的。如果需要,您可以编写自己的单独集合实现。
  • 不要创建 HashSet 的子类,而是覆盖 StoredObject 类上的 equals 和 hashcode 以使用 Type。

标签: java overriding contains hashset


【解决方案1】:

HashMap&lt;Type,StoredObject&gt; 是合适的集合。​​

如果您覆盖equals(Object),那么您还必须覆盖hashCode(实现Comparable 并可能覆盖toString 也不是一个坏主意)。使用 @Override 注释确保您拥有正确的参数类型和拼写 - 很容易出错和调试混乱。

会出什么问题?

  • HashSet 中有很多方法可以覆盖,所以工作量很大。
  • 在 Java 的未来版本中,HashSet 可能会添加更多方法 - 您将如何注意这一点?
  • contains 应该是 O(1) 操作(假设哈希码分布良好),但 OP 实现是 O(n)。
  • 另一个Set 上的Set.equals 将报告不正确的结果。

还要注意,StoredObject.class.isAssignableFrom(o.getClass()) 最好写成o instanceof StoredObject(假设你的isAssignableFrom 是正确的)。

【讨论】:

  • 感谢您为此指出适当的集合。在进一步解决这个问题时,我发现在 Type 是枚举的情况下,使用 Enum Map 甚至更简单,就像我一样。
【解决方案2】:

这个实现安全吗?

绝对不是。 HashSet 上还有其他无法正常工作的方法,例如add(),设置的大小不正确。

此外,该实现将完全破坏 contains 方法的性能,使其在 O(n) 而不是 O(1) 中运行。 p>

如果您需要具有与 equals()hashCode() 实现的对象自然定义不同的相等定义的 Set,请使用 TreeSet 并提供自定义 Comparator

class MySet<E extends StoredObject> extends java.util.TreeSet<E> {
    public MySet() {
        super(Comparator.comparing(StoredObject::getType));
    }
}

我同意Tom Hawtin - tackline,认为HashMap&lt;Type, StoredObject&gt; 是一个更好的选择,因为它允许您为给定的Type 获得StoredObject,否则很难使用Set。它还允许您仅给定一个 Type 就可以检查是否存在,而无需为检查创建一个虚拟的 StoredObject 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2023-03-07
    • 2021-05-24
    • 1970-01-01
    相关资源
    最近更新 更多