我已经看到了有关根据索引值从Set
获取对象的其他问题,我理解为什么这是不可能的。但我无法找到一个很好的解释为什么不允许通过对象获取,所以我想问。
HashSet
由HashMap
支持,因此从中获取对象应该非常简单。就像现在一样,看起来我必须遍历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)
就足够了)?
答案 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)
Set
是Collection
个对象,它将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)