我相信有一个很好的理由,但有人能解释一下为什么java.util.Set接口缺少get(int Index),或任何类似的get()方法吗?

集合似乎很适合把东西放进去,但我找不到一种优雅的方法来从中检索单个项目。

如果我知道我想要的第一项,我可以使用set.iterator().next(),但否则,似乎我必须强制转换到一个数组来检索特定索引的项?

从集合中检索数据的适当方法是什么?(与使用迭代器不同)

我相信它被排除在API之外的事实意味着有一个很好的理由不这样做——有人能启发我吗?

编辑: 这里有一些非常棒的回答,还有一些说“更多的背景”。具体的场景是一个dbUnit测试,在这个测试中,我可以合理地断言从查询返回的集合只有1个项,并且我正在尝试访问该项。

然而,这个问题在没有场景的情况下更有效,因为它仍然更集中:

set和list的区别是什么?

感谢大家的精彩回答。


当前回答

set是一个无序项的集合。如果Set有一个get(int index)就没有意义了,因为 Set没有索引,你只能猜测它的值。

如果你真的想要这个,编写一个方法从Set中获取随机元素。

其他回答

你可以用new ArrayList<T>(set)。get(index)

The reason why the Set interface doesn't have a get index-type call or even something even more basic, such as first() or last(), is because it is an ambiguous operation, and therefore a potentially dangerous operation. If a method returns a Set, and you call, say first() method on it, what is the expected result, given that the a generic Set makes no guarantees on the ordering? The resultant object could very well vary between each call of the method, or it might not and lull you into a false sense of security, until the library you're using changes changes the implementation underneath and now you find that all your code breaks for no particular reason.

这里列出的关于变通办法的建议很好。如果需要索引访问,请使用列表。对泛型Set使用迭代器或toArray时要小心,因为a)不能保证顺序,b)不能保证顺序不会随着后续调用或不同的底层实现而改变。如果你需要介于两者之间的东西,SortedSet或LinkedHashSet就是你想要的。

// 我希望Set界面有一个get-random-元素。

我不确定是否有人这么说过,但你需要明白以下几点:

集合中没有“first”元素。

因为,正如其他人所说,集合没有顺序。集合是一个数学概念,特别不包括排序。

Of course, your computer can't really keep a list of stuff that's not ordered in memory. It has to have some ordering. Internally it's an array or a linked list or something. But you don't really know what it is, and it doesn't really have a first element; the element that comes out "first" comes out that way by chance, and might not be first next time. Even if you took steps to "guarantee" a particular first element, it's still coming out by chance, because you just happened to get it right for one particular implementation of a Set; a different implementation might not work that way with what you did. And, in fact, you may not know the implementation you're using as well as you think you do.

People run into this ALL. THE. TIME. with RDBMS systems and don't understand. An RDBMS query returns a set of records. This is the same type of set from mathematics: an unordered collection of items, only in this case the items are records. An RDBMS query result has no guaranteed order at all unless you use the ORDER BY clause, but all the time people assume it does and then trip themselves up some day when the shape of their data or code changes slightly and triggers the query optimizer to work a different way and suddenly the results don't come out in the order they expect. These are typically the people who didn't pay attention in database class (or when reading the documentation or tutorials) when it was explained to them, up front, that query results do not have a guaranteed ordering.

根据Set集合的定义,Set中的元素是无序的。所以它们不能被索引访问。

但是为什么我们没有一个get(object)方法,不是通过提供索引作为参数,而是提供一个与我们正在寻找的对象相等的对象? 通过这种方式,我们可以访问Set中元素的数据,只需要知道equal方法使用的属性。

Set是一个接口,它的一些实现类是HashSet、TreeSet和LinkedHashSet。它在底层使用HashMap来存储值。因为HashMap不保留顺序,所以不可能通过索引获取值。

你现在肯定在想Set是如何使用HashMap的,因为HashMap存储了一个键和值对,而Set没有。有效的问题。当你在Set中添加一个元素时,它在内部维护一个HashMap,其中键是你想在Set中输入的元素,值是虚拟常量。下面是add函数的内部实现。因此,HashMap中的所有键都将具有相同的常量值。

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}