由于设置条目仅由属性子集(hashCode()
+ equals()
)区分,因此有时需要对集合中包含的原始对象进行操作,这对于{{{ 1}}。我提出的唯一选择是:java.util.Set
- 不是一个非常简洁的解决方案。
集合框架中还有其他替代方案吗?要求是:O(1)获取时间,不基于Map<T, T>
结果重复。
答案 0 :(得分:2)
如果还有一个O(1)操作没有问题,您可以使用方法get(Object)
和set.remove(Object)
模拟缺席方法set.add(Object)
。否则,我会使用你提到的Map<T,T>
或简单的包装类和底层地图。
编辑:Set
不包含get(Object)
的原因是您不需要返回您知道的对象。如果您的对象包含在set中,您只需要检查。
答案 1 :(得分:0)
不在java.util.Collections
本身,而是使用Google Guava,您可以使用Iterables.get
从给定的Iterator
检索任何元素。
通常情况下我不会提倡使用外部库,但考虑到Guava非常强大和有用,我认为没有任何问题。
或者,您可以使用自己的实现迭代该集。
此外,我在这里发现了一个非常有趣的thread来解释这种行为。
答案 2 :(得分:0)
Set
不能包含两个对象o1
和o2
,以便o1.equals(o2
)(此条件中使用“hashCode
”)。
HashSet
正在使用散列图来有效地存储其对象,因此最终HashMap正是您基于hashCode()+equals()
的操作所需的。
答案 3 :(得分:0)
如果你想重用它,我写了这样一个类。 Jayes包含一个类org.eclipse.recommenders.jayes.util.sharing.CanonicalSet
,它允许基于几乎任何可在hashCode()
和equals()
实现中编码的等价关系进行检索。我用它来构建数组等价类。您可以查看CanonicalSet
的这些实现,它们位于同一个包中。
哦,但是,它也只是基于Map<Entry<T>,T>
,所以没有什么神奇的。
答案 4 :(得分:0)
基于HashMap的HashSet代码非常简单:如果你看一下它在JDK中的实现方式,那么实际代码的行很少(忽略构造函数和序列化)码)。
实现这一目标的方法是使用额外的get()
方法实现您自己的HashSet版本
public E get(Object o) {
return map.get(o);
}
答案 5 :(得分:0)
答案 6 :(得分: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);
}