63

我已经看到其他关于Set基于索引值从 ' 获取对象的问题,我理解为什么这是不可能的。但是我无法找到一个很好的解释来解释为什么不允许按对象获取,所以我想我会问。

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

我可以只使用 aMap但我不需要 key:value 对,我只需要一个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)就足够了)?

4

11 回答 11

51

Java Map/Collection 备忘单

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

1)如果它包含,选择是一个地图。顺序重要吗?

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

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

. . 1-1-2) 如果已排序,TreeMap

. 1-2)如果顺序不重要HashMap

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

. 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

于 2014-08-21T12:24:25.840 回答
30

ASet是一个被视为重复Collection的对象a.equals(b) == true,因此尝试获取您已经拥有的相同对象是没有意义的。

如果您尝试get(Object)从集合中提取,aMap可能更合适。

你应该写的是

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

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

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

万一您需要这个,您可以使用Map.

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

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

Bar bar1a = map.get(new Bar(1));
于 2012-12-13T15:56:31.977 回答
5

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

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

于 2012-12-13T15:58:09.437 回答
4

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

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

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

于 2012-12-13T15:59:34.647 回答
0

HashSet 比 HashMap 简单一点。如果你不需要 HashMap 的特性,为什么要使用它?如果像 getObject(ObjectType o) 这样的方法是由 Java 实现的,我们不需要在调用 contains() 方法后遍历集合...

于 2014-07-19T16:41:31.330 回答
0

没有get的原因很简单:

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

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

map.get("key") -> X!

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

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

这没有任何意义,因为你已经有了 X,纯粹主义者会说。

但是现在将其视为非纯粹主义者,看看您是否真的想要这个:

假设我制作了对象 Y,它与 X 的等号匹配,因此 set.get(Y)->X。Volia,然后我可以访问我没有的X的数据。例如,X 有一个名为 get flag() 的方法,我想要它的结果。

现在看看这段代码。

X = map.get(Y);

所以 Y.equals(x) 为真!

但..

Y.flag() == X.flag() = 假。(他们不是平等的吗?)

所以,你看,如果 set 允许你得到这样的对象,那肯定是打破了 equals 的基本语义。稍后你将与 X 的小克隆一起生活,他们都声称它们是相同的,而实际上它们不是。

您需要一张地图来存储东西并使用密钥来检索它。

于 2015-03-05T20:15:36.607 回答
0

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

于 2017-01-13T06:40:59.630 回答
0

我遇到了与线程作者相同的问题,并且我有一个 Set 应该具有 get 方法的真正原因:我覆盖了例如 X 的等于,集合 Set 的内容,因此包含的对象不一定是与检查的相同。在我的场景中,我将删除另一个集合中的语义双精度,并使用“双精度”的一些关系来丰富“原始”,因此我需要“原始”才能删除双精度。

于 2019-11-07T15:44:08.330 回答
0

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

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

于 2020-02-03T09:39:24.417 回答
-1

正如大家之前提到的,没有这样的方法并且有充分的理由。话虽如此,如果您希望使用单线(几乎)从 java 8 中的 HashSet 获取某个对象,只需使用流。在你的情况下,它会是这样的:

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

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

于 2015-01-02T09:48:09.223 回答
-1

get方法 on的一个常见用例Set可能是实现一个实习生集。如果这是您想要实现的目标,请考虑使用 Google Guava 的Interner界面和Interners工厂。

于 2015-10-12T21:08:19.297 回答