从集合中获取任意元素

时间:2011-09-04 11:58:53

标签: java

在许多算法中,您应该迭代一组元素,而该集合不为空。

由于您可能在迭代时更改集合,因此通常会从集合中拉出一个元素,然后执行迭代,可能会在集合中添加或删除元素。这是一个典型的Java代码。

Set<Integer> possibleFactors = Sets.newHashSet(2,3,4,5,6,7,8,100);
while (!possibleFactors.isEmpty()) {
    int factor = possibleFactors.iterator().next();
    for (int i=1;i<10;i++) possibleFactors.remove(i*factor);
}

编辑:正如评论中所述,我会举一个更好的例子。我正在迭代用户选择的文件,我通过检查每个项目的权限来过滤它们。但是,作为优化,如果用户没有某个目录的权限,我将从该集中删除其中的所有文件。

Set<Path> input = Sets.newHashSet(userSelectedPaths);
while (!input.isEmpty()) {
    Path path = input.iterator.next();
    input.remove(path);
    if (!expensivePermissionCheck(path)) {
        input.removeAll(path.getFiles());
    } else {
        processPath(path);
    }
}

然而,循环中的第一行看起来很奇怪。它创建了一个多余的Iterable对象,当我想要的只是集合中的任意元素时,我不关心它的顺序。

除了性能之外,它看起来有点奇怪,而且可读性较差。

有更好的选择吗?也许完全不同的结构?

编辑:或许更好的表述是“如何从一组中弹出任意元素?”

3 个答案:

答案 0 :(得分:5)

Set界面的唯一访问方法是通过iterator()方法或toArray()方法。

如果您有SortedSet,则可以使用first()last()方法直接访问一个项目。

答案 1 :(得分:-1)

实际上它不仅不可读,而且如果该组为空,它也会抛出异常。

在获取next()之前,您应该始终检查hasNext(),然后根据此行动。

答案 2 :(得分:-2)

在集合中没有特定的元素排序。您可以通过提供其值(Set.remove(Object o)或Set.contains(Object o)来删除或检查元素的存在。您可以考虑从集合中删除所有元素,或者将其保留为集合A中的元素使用

不在B组中
Set.removeAll(Set B);

例如

Set<Integer> A = new HashSet();
Set<Integer> B = new HashSet();

add numbers from 1-to-10 into A
add even numbers in range [1, 10] to B

A.removeAll(B);
println(A)

will print all odd numbers, eg those that are in A but not in B.

或者,您可以调用remove()方法,该方法从集合中删除元素(如果存在):

for (int i = 2; i <= 10; i += 2) {
   a.remove(i)
}

它与上面例子中的removeAll()具有相同的效果。

通常,当您处理独特事物的集合并且它们的排序无关紧要时,Set数据结构是合适的。如果要对集合执行Union,Intersection,Diff等操作,则集合很有用(并且很快)。如果您的项目可能重复一次,那么您可以考虑使用Multisets(谷歌收藏),如果您关心事物的排序,那么列表会更有帮助(但性能会更差)。