为什么java.util.Set不包含值getter?有其他选择吗?
由于集合项仅通过属性子集(为什么java.util.Set不包含值getter?有其他选择吗?,java,collections,Java,Collections,由于集合项仅通过属性子集(hashCode()+equals())进行区分,因此有时需要对集合中包含的原始对象进行操作,这在java.util.set中是不可能的。我提出的唯一选择是:Map——这不是一个非常简洁的解决方案 集合框架中还有其他替代方案吗?要求是:O(1)基于hashCode()+equals()结果获取时间和无重复项。不在java.util.Collections本身中,但使用,您可以使用从给定的迭代器中检索任何元素 通常我不会提倡外部库,但考虑到番石榴的强大和实用性,我认为它没
hashCode()
+equals()
)进行区分,因此有时需要对集合中包含的原始对象进行操作,这在java.util.set
中是不可能的。我提出的唯一选择是:Map
——这不是一个非常简洁的解决方案
集合框架中还有其他替代方案吗?要求是:O(1)基于
hashCode()+equals()
结果获取时间和无重复项。不在java.util.Collections
本身中,但使用,您可以使用从给定的迭代器中检索任何元素
通常我不会提倡外部库,但考虑到番石榴的强大和实用性,我认为它没有问题
或者,您可以使用自己的实现来迭代集合
另外,我在这里发现了一个非常有趣的解释这种行为的方法。一个集合
不能包含两个对象o1
和o2
,这样o1.equals(o2
)(在这个标准中没有使用hashCode
)
HashSet
使用hashmap高效地存储其对象,因此最终hashmap正是基于hashCode()+equals()
的操作所需要的 如果你想重用它,我就编写了这样一个类。包含一个类org.eclipse.recommenders.jayes.util.sharing.CanonicalSet
,该类允许基于几乎任何等价关系进行检索,这些等价关系可以在hashCode()
和equals()
实现中进行编码。我用它来构建数组等价类。您可以查看那些CanonicalSet
的实现,它们在同一个包中
哦,但是是的,它也只是基于一个映射
,所以没有什么神奇的地方。基于HashMap的HashSet的代码非常简单:如果你看看它在JDK中的实现方式,实际的代码行非常少(忽略构造函数和序列化代码)
这样做的方法是使用附加的get()
方法实现您自己版本的HashSet
public E get(Object o) {
return map.get(o);
}
你可以从
它装饰java.util.List
以确保不存在重复项,就像java.util.Set是的,不能共享相等的对象有点痛苦。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);
如果一个以上的O(1)操作没有问题,您可以使用一对方法set.remove(Object)
和set.add(Object)
模拟缺席方法get(Object)
。否则,我将使用您提到的Map
,或者使用简单的包装类和底层Map
EDIT:之所以Set
不包含get(Object)
,是因为您不需要返回您知道的对象。您只需检查对象是否包含在集合中。您在寻找吗?啊,所以您想要集合中的原始对象。最简单的方法就是你的地图解决方案。“这不是很方便的原因吗?”Marcin不,这就是你需要HashMap的原因。这是标准API中另一个基于哈希的集合。这是最省力的解决方案。这不是一个非常漂亮的解决方案,但您没有非常漂亮的要求:|@dhrubajyotigogi尝试从HashSet
提取原始对象。这就是我想做的。映射是正确的解决方案。但它不再是O(1)。这不是他想要的:他想从一个集合中检索一个对象,该集合在恒定时间内等于另一个对象。@arshajii我理解,但是Set接口不提供用于检索对象及其属性的get方法,因为这不是Set的意图。他要求通过使用hashcode和equals有效区分对象,这正是Hash映射的目的。所以你是说他应该使用映射,正如他已经尝试过的那样?这实际上取决于他对原始对象的定义。它是指创建的同一实例(内存方面)还是指具有完全相同属性的对象。对于后者,他可以安全地使用Hashmap。我真的想知道,如果是这样的话,同样的例子需要什么。
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);
}