为什么java.util.Set<;V>;接口不提供get(对象o)方法?

为什么java.util.Set<;V>;接口不提供get(对象o)方法?,java,generics,collections,Java,Generics,Collections,我知道一个集合中只允许一个符合.equals()的对象实例,如果已经有一个等价对象,则不应该“需要”从集合中获取对象,但我仍然希望有一个.get()方法返回集合中对象的实际实例(或null)给定一个等效对象作为参数 关于它为什么设计成这样有什么想法/理论吗 我通常不得不通过使用地图来解决这个问题,使键和值相同,或者类似的东西 编辑:我认为到目前为止人们还不理解我的问题。我想要集合中已经存在的确切对象实例,而不是.equals()返回true的可能不同的对象实例 至于我为什么想要这种行为,通常.e

我知道一个集合中只允许一个符合.equals()的对象实例,如果已经有一个等价对象,则不应该“需要”从集合中获取对象,但我仍然希望有一个.get()方法返回集合中对象的实际实例(或null)给定一个等效对象作为参数

关于它为什么设计成这样有什么想法/理论吗

我通常不得不通过使用地图来解决这个问题,使键和值相同,或者类似的东西

编辑:我认为到目前为止人们还不理解我的问题。我想要集合中已经存在的确切对象实例,而不是.equals()返回true的可能不同的对象实例

至于我为什么想要这种行为,通常.equals()不会考虑对象的所有属性。我想提供一些虚拟的查找对象,并返回集合中的实际对象实例。

好吧,如果您已经从集合中“获取”了对象,您不需要获取()它,是吗?;-)


我认为你使用地图的方法是正确的。听起来,您正试图通过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?..