7

由于集合条目仅通过属性子集 ( hashCode()+ equals()) 来区分,因此有时需要对集合中包含的原始对象进行操作,而java.util.Set. 我想出的唯一选择是:Map<T, T>- 不是一个非常简洁的解决方案。

集合框架中还有其他选择吗?要求是:O(1) 获取时间并且基于hashCode() + equals()结果没有重复。

4

7 回答 7

2

如果多一个 O(1) 操作没有问题,你可以用一对方法和模拟缺席方法。否则,我会使用你提到的或带有底层映射的简单包装类。get(Object)set.remove(Object)set.add(Object)Map<T,T>

编辑Set:不包含的原因get(Object)是您不需要返回您知道的对象。您只需要检查您的对象是否包含在集合中。

于 2015-01-04T16:33:44.687 回答
0

是的,这有点痛苦,不能共享相同的对象。Set API 的问题是缺少特定的 addAndGet:

AddOnceSet<String> set = new AddOnceSet<>();
String s = in.readLine();
s = set.addOnce(s); // The new s is equal, and identical to the first added one.

s = set.getOnce(s);

不幸的是,这不适合集合 API。我希望这可以在 Java 8+ 中。在 Java 8 中,您可以添加一个默认为addOnce和的接口getOnce

像你说的那样实施,在:

private Map<T, T> sharedThings = new HashMap<>().

public T shareThing(T s) {
    String t = sharedThings.get(s);
    if (t == null) {
        t = s;
        sharedStrings.put(t, t);
    }
    return t;
}

...

public void setT(T t) {
    this.t = sharedThing(t);
}
于 2013-07-11T14:06:32.980 回答
0

ASet不能包含两个对象o1o2因此o1.equals(o2) (hashCode此标准中使用否)。

AHashSet正在使用 hashmap 来有效地存储其对象,因此最终 HashMap 正是hashCode()+equals()基于操作所需要的。

于 2013-07-11T13:19:54.237 回答
0

您可以使用来自commons-collections 的SetUniqueList

它装饰 ajava.util.List以确保不存在重复项,就像 a 一样java.util.Set

于 2013-07-11T13:40:44.917 回答
0

如果你想重用它,我写了这样一个类。Jayes包含一个类,它允许基于您可以在 a和实现org.eclipse.recommenders.jayes.util.sharing.CanonicalSet中编码的几乎任何等价关系进行检索。我用它来构建数组等价类。您可以查看 的那些实现,它们在同一个包中。hashCode()equals()CanonicalSet

哦,但是是的,它也只是基于 a Map<Entry<T>,T>,所以没什么神奇的。

于 2013-07-11T13:27:56.083 回答
0

基于 HashMap 的 HashSet 的代码非常简单:如果您查看它在 JDK 中的实现方式,实际代码行数很少(忽略构造函数和序列化代码)。

这样做的方法是使用附加get()方法实现您自己的 HashSet 版本

public E get(Object o) {
   return map.get(o);
}
于 2013-07-11T13:28:22.333 回答
0

不是java.util.Collections本身,而是使用Google GuavaIterator ,您可以从给定的using中检索任何元素Iterables.get

通常我不会提倡外部库,但鉴于 Guava 非常强大和有用,我认为它没有问题。

或者,您可以使用自己的实现来迭代集合。


此外,我在这里找到了一个非常有趣的线程来解释这种行为。

于 2013-07-11T13:13:52.620 回答