想象一下,我有几个看起来像这样的对象
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方法
我想要这个的原因是我用循环遍历一个对象图。我不想陷入其中。
答案 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 */
}