为什么java.util.Set<;V>;接口不提供get(对象o)方法?
我知道一个集合中只允许一个符合.equals()的对象实例,如果已经有一个等价对象,则不应该“需要”从集合中获取对象,但我仍然希望有一个.get()方法返回集合中对象的实际实例(或null)给定一个等效对象作为参数 关于它为什么设计成这样有什么想法/理论吗 我通常不得不通过使用地图来解决这个问题,使键和值相同,或者类似的东西 编辑:我认为到目前为止人们还不理解我的问题。我想要集合中已经存在的确切对象实例,而不是.equals()返回true的可能不同的对象实例 至于我为什么想要这种行为,通常.equals()不会考虑对象的所有属性。我想提供一些虚拟的查找对象,并返回集合中的实际对象实例。好吧,如果您已经从集合中“获取”了对象,您不需要获取()它,是吗?;-)为什么java.util.Set<;V>;接口不提供get(对象o)方法?,java,generics,collections,Java,Generics,Collections,我知道一个集合中只允许一个符合.equals()的对象实例,如果已经有一个等价对象,则不应该“需要”从集合中获取对象,但我仍然希望有一个.get()方法返回集合中对象的实际实例(或null)给定一个等效对象作为参数 关于它为什么设计成这样有什么想法/理论吗 我通常不得不通过使用地图来解决这个问题,使键和值相同,或者类似的东西 编辑:我认为到目前为止人们还不理解我的问题。我想要集合中已经存在的确切对象实例,而不是.equals()返回true的可能不同的对象实例 至于我为什么想要这种行为,通常.e
我认为你使用地图的方法是正确的。听起来,您正试图通过equals()方法“规范化”对象,我一直按照您的建议使用映射来实现这一点。我想您已经回答了自己的问题:它是多余的
Set提供Set#contains(Object o),它提供所需Set#get(Object o)的等效标识测试,并像预期的那样返回布尔值 问题是:Set不是用于“获取”对象,而是用于添加和测试是否存在。 我知道你在找什么,我也遇到过类似的情况,最后在key和value中使用了同一对象的贴图 编辑:只是澄清一下:“我想要已经在集合中的确切对象实例,而不是.equals()返回true的可能不同的对象实例。” 这没有道理。假设你这样做:
Set<Foo> s = new Set<Foo>();
s.Add(new Foo(...));
...
Foo newFoo = ...;
如果希望仅当集合中的对象为==newFoo时才为true,请使用对象标识实现Foo的equals和hashCode。或者,如果您试图将多个相等的对象映射到一个规范的原始对象,那么映射可能是正确的选择。我认为期望的是相等真正地表示某种相等,而不仅仅是两个对象具有相同的主键,例如。如果equals表示两个真正相等的对象,那么get将是多余的。您想要的用例建议一个映射,可能是键的另一个值,表示主键,而不是整个对象,然后相应地正确地实现equals和hashcode。虽然puriture参数确实使方法
get(object)
可疑,但其基本意图并没有意义
有各种类和接口族稍微重新定义了等于(对象)
。我们只需要查看集合接口。例如,ArrayList和LinkedList可以相等;它们各自的内容只需相同且顺序相同即可
因此,在集合中找到匹配元素有很好的理由。也许一个更明确的表示意图的方法是使用类似
public interface Collection<E> extends ... {
...
public E findMatch(Object o) throws UnsupportedOperationException;
...
}
公共接口集合扩展了。。。{
...
公共E-findMatch(对象o)抛出不支持的操作异常;
...
}
请注意,此API的值比集合中的值更宽
至于问题本身,我没有任何理论来解释为什么省略了这样一个操作。我要说的是,最小生成集参数不成立,因为集合API中定义的许多操作都是出于方便和效率的考虑。我不确定您是否在寻找集合为何以这种方式运行的解释,或者寻找它所带来问题的简单解决方案。其他答案涉及前者,因此这里有一个针对后者的建议 您可以迭代集合的元素,并使用equals()方法测试每个元素是否相等。它易于实现,几乎不容易出错。显然,如果不确定元素是否在集合中,请事先检查contains()方法 例如,与HashSet的contains()方法相比,这种方法效率不高,后者确实“查找”了存储的元素,但不会返回它。如果您的集合可能包含许多元素,那么它甚至可能是使用“更重”的解决方案(如您提到的map实现)的一个原因。但是,如果它对您如此重要(我确实看到了拥有此功能的好处),那么它可能是值得的。有一个持久集的实现(由一个红/黑树支持),顺便说一句,它包含了一个似乎可以做您想要做的事情的方法。它返回一个三元组:
Option
的对象,该对象为空或包含找到的对象(如果该对象存在于集合中)MyElementType found = hayStack.split(needle)._2().orSome(hay);
convertSetToMap(myset).get(myobject);
所以我知道你可能有两个相等的对象,但它们不是同一个实例 比如
Integer a = new Integer(3);
Integer b = new Integer(3);
在这种情况下,a等于(b),因为它们引用相同的内在值,但a!=b因为它们是两个不同的物体
还有其他的Set实现,例如,它们在项目之间进行不同的比较
但是,我认为您正在尝试将不同的理念应用于Java。如果你的对象是相等的(a.equals(b)),尽管a和b有不同的状态或意义,但这里有问题。您可能希望将该类拆分为两个或多个实现公共接口的语义类,或者重新考虑.equals和.hashCode
如果你有约书亚·布洛赫(Joshua Bloch)的,请看一看名为“覆盖平等时遵守总合同”和“最小化易变性”的章节。只需使用映射解决方案。。
K target = ...;
Set<K> set = ...;
for (K element : set) {
if (target.equals(element)) {
return element;
}
}
Object fromSet = set.tailSet(obj).first();
if (! obj.equals(fromSet)) fromSet = null;
public <T> T findInSet(T findMe, Set<T> inHere){
inHere.retainAll(Arrays.asList(findMe));
if(!inHere.isEmpty){
return inHere.iterator().next();
}
return null;
}
class Element {
public int hashCode() {return sumOfKeyFields()}
public boolean equals(Object e) {keyField1.equals(e) && keyField2.equals(e) && ..}
public Map<MyObject, MyObject> convertSetToMap(Set<MyObject> set)
{
Map<MyObject, MyObject> myObjectMap = new HashMap<MyObject, MyObject>();
for(MyObject myObject: set){
myObjectMap.put(myObject, myObject);
}
return myObjectMap
}
convertSetToMap(myset).get(myobject);
searchSet(Set ss, Object searchFor){
Iterator it = ss.iterator();
while(it.hasNext()){
Object s = it.next();
if(s != null && s.equals(searchFor)){
return s;
}
}
TreeSet myTreeSet<MyObject> = new TreeSet();
:
:
// Equivalent of a get() and a null-check, except for the incorrect value sitting in
// returnedMyObject in the not-equal case.
MyObject returnedMyObject = myTreeSet.ceiling(comparisonMyObject);
if ((null != returnedMyObject) && returnedMyObject.equals(comparisonMyObject)) {
:
:
}
@ApplicationPath("/")
public class GlobalEventCollectorApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(EventReceiverService.class);
classes.add(VirtualNetworkEventSerializer.class);
return classes;
}
}
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.get(0); // will return value 1
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
//assume it has get method
set.get(0); // what are you expecting this to return. 1?..