由于集合条目仅通过属性子集 ( hashCode()
+ equals()
) 来区分,因此有时需要对集合中包含的原始对象进行操作,而java.util.Set
. 我想出的唯一选择是:Map<T, T>
- 不是一个非常简洁的解决方案。
集合框架中还有其他选择吗?要求是:O(1) 获取时间并且基于hashCode() + equals()
结果没有重复。
由于集合条目仅通过属性子集 ( hashCode()
+ equals()
) 来区分,因此有时需要对集合中包含的原始对象进行操作,而java.util.Set
. 我想出的唯一选择是:Map<T, T>
- 不是一个非常简洁的解决方案。
集合框架中还有其他选择吗?要求是:O(1) 获取时间并且基于hashCode() + equals()
结果没有重复。
如果多一个 O(1) 操作没有问题,你可以用一对方法和模拟缺席方法。否则,我会使用你提到的或带有底层映射的简单包装类。get(Object)
set.remove(Object)
set.add(Object)
Map<T,T>
编辑Set
:不包含的原因get(Object)
是您不需要返回您知道的对象。您只需要检查您的对象是否包含在集合中。
是的,这有点痛苦,不能共享相同的对象。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);
}
ASet
不能包含两个对象o1
,o2
因此o1.equals(o2
) (hashCode
此标准中使用否)。
AHashSet
正在使用 hashmap 来有效地存储其对象,因此最终 HashMap 正是hashCode()+equals()
基于操作所需要的。
您可以使用来自commons-collections 的SetUniqueList
它装饰 ajava.util.List
以确保不存在重复项,就像 a 一样java.util.Set
。
如果你想重用它,我写了这样一个类。Jayes包含一个类,它允许基于您可以在 a和实现org.eclipse.recommenders.jayes.util.sharing.CanonicalSet
中编码的几乎任何等价关系进行检索。我用它来构建数组等价类。您可以查看 的那些实现,它们在同一个包中。hashCode()
equals()
CanonicalSet
哦,但是是的,它也只是基于 a Map<Entry<T>,T>
,所以没什么神奇的。
基于 HashMap 的 HashSet 的代码非常简单:如果您查看它在 JDK 中的实现方式,实际代码行数很少(忽略构造函数和序列化代码)。
这样做的方法是使用附加get()
方法实现您自己的 HashSet 版本
public E get(Object o) {
return map.get(o);
}
不是java.util.Collections
本身,而是使用Google GuavaIterator
,您可以从给定的using中检索任何元素Iterables.get
。
通常我不会提倡外部库,但鉴于 Guava 非常强大和有用,我认为它没有问题。
或者,您可以使用自己的实现来迭代集合。
此外,我在这里找到了一个非常有趣的线程来解释这种行为。