为什么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)如果sorting , TreeSet
你的最后一句话就是答案。
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,所以在技术上不是单行的,但是如果筛选器正确实现,它应该比对传统元素的传统迭代更快。