为什么java.util.Set不包含值getter?有替代品吗?

时间:2013-07-11 13:04:59

标签: java collections

由于设置条目仅由属性子集(hashCode() + equals())区分,因此有时需要对集合中包含的原始对象进行操作,这对于{{{ 1}}。我提出的唯一选择是:java.util.Set - 不是一个非常简洁的解决方案。

集合框架中还有其他替代方案吗?要求是:O(1)获取时间,不基于Map<T, T>结果重复。

7 个答案:

答案 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不能包含两个对象o1o2,以便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)

您可以使用SetUniqueList

中的commons-collections

它装饰java.util.List以确保不会出现像java.util.Set那样重复的内容。

答案 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中,您可以添加具有addOncegetOnce默认值的接口。

如你所说的实施:

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);
}