是否有一个忽略.equals的java Set集合

时间:2013-12-31 18:35:48

标签: java reflection set

我正在做一些奇怪的事情。我想创建一个Set,但是我想忽略那些对象上的equals覆盖,而是我想为等于比较(真的)做obj1 == obj2。

想象一下,我有几个看起来像这样的对象

public static class BrokenEquals
{
    @Override
    public int hashCode()
    {
        return 1;
    }


    @Override
    public boolean equals(Object obj)
    {
        return true;
    }
}

如果我这样做

    Set<Object> objs = new HashSet<>();
    objs.add(new BrokenEquals());
    objs.add(new BrokenEquals()); // objs.size() == 1

显然,Set的大小为1(因为两个对象是&#34;相等&#34;)。相反,我希望该集合包含两个不同的对象。

但是,如果我这样做

    BrokenEquals obj = new BrokenEquals();
    Set<Object> objs = new HashSet<Object>();
    objs.add(obj);
    objs.add(obj); // objs.size() == 1

我希望集合的大小为1;

我无法更改.equals方法

我想要这个的原因是我用循环遍历一个对象图。我不想陷入其中。

4 个答案:

答案 0 :(得分:7)

您可以使用IdentityHashMap并忽略这些值(键将形成一组)。

在线提供IdentityHashSet的各种实现方式。例如,你可以使用Guava和Sets.newIdentityHashSet

Set<Object> set = Sets.newIdentityHashSet();
objs.add(obj);
objs.add(obj); // Size will be 1

请注意,我也会尝试以破碎的方式修复实施equals的类...

答案 1 :(得分:3)

有点儿。 Java有IdentityHashMap,它使用引用来检查相等性但它是一个映射,而不是一个集合。出于某种原因,我不认为java有一个Set版本所以解决方法是使用Map,但把密钥作为键和值。

 IdentityHashMap<Object,Object> map = new IdentityHashMap<>();
 map.put(obj,obj);

Set<Object> set = map.keyset();

答案 2 :(得分:1)

您可以扩展该类并覆盖equals方法:

public class FixedEquals extends BrokenEquals
{   
    @Override
    public boolean equals(Object obj)
    {
        return this == obj;
    }
}

您还可以创建一个正确实现equals的包装类,并仅将包装值插入到集合中:

public static class Wrapper
{   
    private final Object obj;

    public Wrapper(Object obj) { this.obj = obj; }

    @Override
    public boolean equals(Object obj)
    {
        return this.obj == ((Wrapper)obj).obj;
    }
}

答案 3 :(得分:0)

这个怎么样

public Class ReferenceSet<T> extends Set<T> {
    private class Entry<T> {
        private T reference;

        public Entry(T reference) {
            this.reference = reference
        }
        public boolean equals(Object that) {
            return this.reference == ((Entry<T>)that).reference;
        }
    }
    private Set<Entry<T>> data;

    /* Pass all calls to set methods to data */
}