为什么java.util.HashSet没有get(Object o)方法?

时间:2012-12-13 15:53:36

标签: java hashset

我已经看到了有关根据索引值从Set获取对象的其他问题,我理解为什么这是不可能的。但我无法找到一个很好的解释为什么不允许通过对象获取,所以我想问。

HashSetHashMap支持,因此从中获取对象应该非常简单。就像现在一样,看起来我必须遍历HashSet中的每个项目并测试相等性,这似乎是不必要的。

我可以使用Map,但我不需要密钥:值对,我只需要一个Set

例如说我有Foo.java

package example;

import java.io.Serializable;

public class Foo implements Serializable {

    String _id;
    String _description;

    public Foo(String id){
        this._id = id
    }

    public void setDescription(String description){
        this._description = description;
    }

    public String getDescription(){
        return this._description;
    }

    public boolean equals(Object obj) {
        //equals code, checks if id's are equal
    }

    public int hashCode() {
        //hash code calculation
    }

}

Example.java

package example;

import java.util.HashSet;

public class Example {

    public static void main(String[] args){
        HashSet<Foo> set = new HashSet<Foo>();

        Foo foo1 = new Foo("1");
        foo1.setDescription("Number 1");

        set.add(foo1);
        set.add(new Foo("2"));

        //I want to get the object stored in the Set, so I construct a object that is 'equal' to the one I want.
        Foo theFoo = set.get(new Foo("1")); //Is there a reason this is not allowed?
        System.out.println(theFoo.getDescription); //Should print Number 1
    }

}

是因为equals方法是为了测试“绝对”平等而不是“逻辑”平等(在这种情况下contains(Object o)就足够了)?

11 个答案:

答案 0 :(得分:46)

Java Map / Collection备忘单

它是否只包含键/值对或值?

  

1)如果它包含,则选择是地图。订单重要吗?

     

。 1-1)如果,请按照插入顺序或按键排序?

。 。 1-1-1)如果有序, LinkedHashMap

。 。 1-1-2)如果排序, TreeMap

。 1-2)如果订单重要, HashMap

  

2)如果它只存储,则选择是一个集合。它会包含重复吗?

。 2-1)如果 ArrayList

  

。 2-2)如果包含重复项,则主要任务是搜索元素   (包含/删除)?

。 。 2-2-1)如果 ArrayList

  

。 。 2-2-2)如果,订单是否重要?

。 。 。 2-2-2-1)如果订单重要, HashSet

  

。 。 。 2-2-2-2)如果,请按照插入顺序或按值排序?

。 。 。 。 2-2-2-2-1)如果订购 LinkedHashSet

。 。 。 。 2-2-2-2-2)如果排序 TreeSet

答案 1 :(得分:24)

SetCollection个对象,它将a.equals(b) == true视为重复项,因此尝试获取您已有的同一对象是没有意义的。

如果您尝试从集合中get(Object)Map可能更合适。

你应该写的是

Map<String, String> map = new LinkedHashMap<>();

map.put("1", "Number 1");
map.put("2", null);
String description = set.get("1");
  

如果一个对象不在集合中(基于等于),添加它,如果它在集合中(基于等于)给我该集合的该对象的实例

如果你需要这个,你可以使用Map

Map<Bar, Bar> map = // LinkedHashMap or ConcurrentHashMap

Bar bar1 = new Bar(1);
map.put(bar1, bar1);

Bar bar1a = map.get(new Bar(1));

答案 2 :(得分:5)

你的最后一句话就是答案。

get(Object o)将通过HashSet查找另一个等于o的对象(使用equals(o)方法)。所以它确实与contains(o)相同,只是没有返回相同的结果。

答案 3 :(得分:4)

如果您想知道new Foo("1");中已存在set对象,则需要使用contains方法:

boolean present =  set.contains(new Foo("1"));

不支持get种方法,即set.get(new Foo("1"));,因为它没有意义。您已经拥有了对象,new Foo("1")然后您将通过get方法查看哪些额外信息。

答案 4 :(得分:0)

HashSet比HashMap稍微简单一些。如果您不需要HashMap的功能,为什么要使用它?如果像getObject(ObjectType o)这样的方法是由Java实现的,那么在调用contains()方法之后我们就不需要迭代它了...

答案 5 :(得分:0)

没有得到的原因很简单:

如果你需要从集合中获取对象X是因为你需要X中的东西而你没有对象。

如果您没有该对象,则需要一些方法(键)来定位它。 ..名字,数字,永远。那是什么地图是正确的。

map.get(“key”) - &gt; X!

设置没有键,你需要遍历它们来获取对象。

那么,为什么不添加一个方便的get(X) - &gt; X

这没有道理,因为你已经有了X,纯粹主义者会说。

但现在把它视为非纯粹主义者,看看你是否真的想要这个:

假设我创建了对象Y,它与X的等号匹配,因此set.get(Y) - &gt; X. Volia,然后我可以访问我没有的X数据。比方说,例如X有一个名为get flag()的方法,我希望得到结果。

现在看看这段代码。

ý

X = map.get(Y);

所以Y.equals(x)是真的!

,但..

Y.flag()== X.flag()= false。 (他们不等于吗?)

所以,你看,如果set允许你得到像这样的对象肯定会打破equals的基本语义。之后你会生活在X的所有小克隆中,所以当它们不存在时它们是相同的。

你需要一张地图,存储东西并使用钥匙来检索它。

答案 6 :(得分:0)

如果您只想知道Hashset中的内容,可以使用.toString();方法显示以逗号分隔的所有Hashset内容。

答案 7 :(得分:0)

我遇到了与线程作者相同的问题,并且我有一个真正的原因 Set应该具有get方法: 我重写了等于X,集合Set的内容等包含 对象不一定与选中的对象相同。在我的情况下,我将删除 语义在另一个集合中加倍,并使“原始”与某些关系丰富 的“双”,所以我需要“原始”才能删除双。

答案 8 :(得分:0)

get(Object o)在将一个信息链接到其他信息时非常有用,就像在HashMap中找到键值对一样。因此,对一个信息使用get()方法可以获取第二个信息,反之亦然

现在,如果HashSet提供get(Object o)方法,则需要传递一个对象。因此,如果您有要传递给get(Object o)方法的对象,这意味着您已经有了该对象,那么get(Object o)方法的需求是什么。

答案 9 :(得分:-1)

正如大家之前提到的那样,没有这样的方法,而且有充分的理由。话虽这么说,如果你想使用单行(几乎)从Java 8中的HashSet中获取某个对象,只需使用流。在你的情况下,它会是这样的:

Foo existing = set.stream().filter(o -> o.equals(new Foo("1"))).collect(Collectors.toList()).iterator().next();

请注意,如果元素不存在则会抛出异常,因此它在技术上不是单行,但如果过滤器正确实现,它应该比传统迭代更快地集合元素。

答案 10 :(得分:-1)

getSet方法的常见用例可能是实现实习集。如果这是您尝试实现的目标,请考虑使用Google Guava的Interner界面和Interners工厂。