2

我想利用一个独特的 java 集合,它可以接受一种策略来确定成员对象在集合初始化时是否“相等”。

我需要这样做的原因是因为我需要添加到此集合的类的 equals 方法已经实现以满足其他(更合适的)功能。在特定情况下,此集合实例中的唯一性标准只需要检查类的一个变量,而不是在 equals 方法中检查的多个变量。我宁愿避免装饰对象,因为我从不同的库中收集它们,并且循环进行装饰会很昂贵(并且可能会使我的代码变得混乱)。

我意识到这不会是一个 Set 因为它会破坏Java 的 Set 合同,但我只是觉得这个问题以前一定遇到过。我认为GuavaApache Collections会提供一些东西,但似乎没有运气。有人知道任何提供此类功能的可用库吗?我应该完全接受不同的解决方案吗?

4

3 回答 3

3

您可以使用自定义比较器和 TreeSet 或 TreeMap 吗?或者使用 Key 具有您的标准的地图?HashSet 只是 HashMap 的包装器,因此使用映射应该更昂贵。

于 2013-01-10T17:10:43.340 回答
1

That is not really practical. Consider for instance two instances of a class C which you consider equivalent.

Now you do:

set.add(c1);
set.remove(c2);

Should the set be empty after that? What about .retainAll(), .removeAll()?

Your best bet here is to create your own class which wraps over class C, deletages whatever is needed to be delegated, and have this wrapper class implement .hashCode() and .equals() (and possibly Comparable of itself too). With such a class, you can just go on and use classical sets and maps.

于 2013-01-10T17:16:52.900 回答
1

Guava 有一个 Equivalence,它可以让你定义两个对象是否等价。

它还具有 Equivalence.Wrapper 包装任意对象并将 equals() 和 hashCode() 委托给等价中的实现,而不是它们自己的实现。

所以你可以做这样的事情:

public class MySet<T> implements Set<T> {

    private final Equivalence<T> equivalence;

    private final Set<Wrapper<T>> delegate = new HashSet<Wrapper<T>>();

    public MySet(Equivalence<T> equivalence) {
        this.equivalence = equivalence;
    }

    public boolean add(T t) {
        return delegate.add(equivalence.wrap(t));
    }

    // other Set methods

}
于 2013-01-10T17:23:07.990 回答