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

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

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

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

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

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

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

set和list的区别是什么?

感谢大家的精彩回答。


当前回答

这就引出了一个问题,什么时候应该使用集合,什么时候应该使用列表。通常,建议是这样的:

如果需要有序数据,请使用List 如果你需要唯一的数据,使用一个集合 如果两者都需要,可以使用SortedSet(用于按比较器排序的数据)或OrderedSet/UniqueList(用于按插入排序的数据)。不幸的是,Java API还没有OrderedSet/UniqueList。

第四种经常出现的情况是,两者都不需要。在这种情况下,你会看到一些程序员使用列表,一些使用集合。就我个人而言,我觉得把set看作一个没有顺序的列表是非常有害的——因为它真的是另一种野兽。除非你需要集唯一性或集相等性,否则总是倾向于列表。

其他回答

因为集合没有顺序。有些实现可以(特别是那些实现java.util.SortedSet接口的实现),但这不是集合的一般属性。

如果您试图以这种方式使用集合,则应该考虑使用列表。

我能想到的在集合中使用数值索引的唯一原因是为了迭代。为此,请使用

for(A a : set) { 
   visit(a); 
}

如果你要在一个集合中通过索引进行大量的随机访问,你可以得到它的元素的数组视图:

Object[] arrayView = mySet.toArray();
//do whatever you need with arrayView[i]

但它有两个主要缺点:

它的内存效率不高,因为需要为整个集合创建一个数组。 如果集合被修改,视图就会过时。

要获取Set中的元素,我使用以下命令:

public T getElement(Set<T> set, T element) {
T result = null;
if (set instanceof TreeSet<?>) {
    T floor = ((TreeSet<T>) set).floor(element);
    if (floor != null && floor.equals(element))
    result = floor;
} else {
    boolean found = false;
    for (Iterator<T> it = set.iterator(); !found && it.hasNext();) {
    if (true) {
        T current = it.next();
        if (current.equals(element)) {
        result = current;
        found = true;
        }
    }
    }
}
return result;
}

这就引出了一个问题,什么时候应该使用集合,什么时候应该使用列表。通常,建议是这样的:

如果需要有序数据,请使用List 如果你需要唯一的数据,使用一个集合 如果两者都需要,可以使用SortedSet(用于按比较器排序的数据)或OrderedSet/UniqueList(用于按插入排序的数据)。不幸的是,Java API还没有OrderedSet/UniqueList。

第四种经常出现的情况是,两者都不需要。在这种情况下,你会看到一些程序员使用列表,一些使用集合。就我个人而言,我觉得把set看作一个没有顺序的列表是非常有害的——因为它真的是另一种野兽。除非你需要集唯一性或集相等性,否则总是倾向于列表。