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

我已经看到其他问题关于从基于索引值获取对象,我明白为什么这是不可能的。 但是我还没有find一个很好的解释,为什么一个逐个对象是不允许的,所以我想问。

HashSet由一个HashMap支持,所以从它获得一个对象应该是非常简单的。 就像现在,看来我将不得不迭代HashSet中的每个项目,并testing似乎不必要的相等性。

我可以只使用HashMap,但是我不需要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方法是为了testing“绝对”的平等而不是“逻辑的”平等(在这种情况下包含(Object o)就足够了)?

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

如果你想从一个集合中获得(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)); 

Java地图/收集备忘录

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

1)如果它包含 ,则select一个地图。 订单重要吗?

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

。 。 1-1-1)如果命令, LinkedHashMap

。 。 1-1-2)如果sorting, TreeMap

。 1-2)如果顺序不重要,则使用HashMap

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

。 2-1)如果ArrayList

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

。 。 2-2-1) ArrayList

。 。 2-2-2)如果 ,命令是否重要?

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

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

。 。 。 。 2-2-2-2-1)如果命令LinkedHashSet

。 。 。 。 2-2-2-2-2)如果sortingTreeSet

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

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

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

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

get一种方法,即set.get(new Foo("1")); 不被支持,因为它没有任何意义。 你已经有了对象,即new Foo("1")那么你将通过get方法查看哪些额外的信息。

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

没有得到的原因很简单:

如果你需要从集合中获取对象X,因为你需要从X中获得一些东西,而你没有这个对象。

如果你没有对象,那么你需要一些手段(键)来find它。 他们的名字,一个数字。 那是什么地图是正确的。

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()= false。 (他们不等于?)

所以,你看,如果设置允许你得到这样的对象它肯定是要打破平等的基本语义。 后来,你将要生活在一起的小克隆人,他们都不相信他们是一样的。

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

这是迭代Hashset的一个快速方法 –

 Set<Integer> integerSet=new HashSet<Integer>(); integerSet.add(4); integerSet.add(1); integerSet.add(4); integerSet.add(45); integerSet.add(2); for (Object anIntegerSet : integerSet) System.out.println(anIntegerSet); 

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

我们希望能够直接通过键值访问元素,而不是通过search数组中的键值来首先确定其位置。 (这就是为什么Set接口的方法contains(obj)而不是get(index) 。)

数据结构:使用Java进行抽象和devise,Koffman

Set的一个get方法的常见用例可能是实现一个实习集。 如果这就是你想要实现的,可以考虑使用Google Guava的Interner接口和Interners工厂。

正如大家所提到的,没有这样的方法,并有很好的理由。 也就是说,如果你希望从java 8的HashSet中使用单线程(几乎)获得某个对象,那么只需使用stream。 在你的情况下,它会是这样的:

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

请注意,如果元素不存在,则会抛出exception,所以在技术上不是单行的,但是如果筛选器正确实现,它应该比对传统元素的传统迭代更快。