在浏览列表时删除列表的随机元素

时间:2015-03-24 13:40:11

标签: java concurrency iterator

根据我的阅读,在迭代列表时删除元素是安全的。 (而不是为每个循环使用简单)。

假设我有一个元素列表,我想访问所有元素,但是当我访问每个元素时,我将访问它的邻居(注意我有一个地图,每个元素都会给我它的邻居)因此,我会 必须从原始列表中删除其他元素。因此我无法使用 iterator.remove()。

这样做的好方法是什么,也就是说,从列表中删除元素而不是使用迭代器处于某个位置?

我有一个想法如下,将我的元素放在地图中,值为 一个布尔值,(对于访问为true,否则为false)。 因此,我浏览了我的列表,并且对于每个元素我设置它访问了真,如果一个如果它的邻居我也看到访问该元素时,我也将它们设置为真。

2 个答案:

答案 0 :(得分:0)

使用for循环而不是foreach迭代项目。然后根据需要删除。以下是从List

中删除偶数元素的示例
import java.util.List;
import java.util.ArrayList;

class Test {
    public static void main(String[] args){
            final List<Integer> ints = new ArrayList<Integer>();
            ints.add(100);
            ints.add(1);
            ints.add(15);
            ints.add(42);
            ints.add(187);

            System.out.println("Original List");
            for(Integer i: ints){
                    System.out.println(i);
            }

            /* Remove any even elements from the list */
            for(int i=0; i < ints.size(); i++){
                    if(ints.get(i) % 2 == 0){
                            ints.remove(i);
                    }
            }

            System.out.println("\nModified List");
            for(Integer i: ints){
                    System.out.println(i);
            }

    }
}

答案 1 :(得分:0)

让我们假设您正在讨论的输入列表是ArrayList

以下方法将为您提供O(N)行为(至少对于OpenJDK Java 6到Java 8):

  1. 创建一个HashSet。

  2. 迭代输入列表中的元素:

    1. 访问该元素并将其添加到集合中(如果应将其删除)
    2. 访问元素的邻居,并将任何应删除的元素添加到集合中。
  3. 致电list.removeAll(set)

  4. removeAll的{​​{1}}方法调用内部ArrayList方法(see here)。此方法对batchRemove的后备阵列执行单次传递,删除元素并填充孔。它通过调用ArrayList来测试每个元素以查看是否应该删除它。对于set.contains(elem),该测试为HashSet,因此O(1)调用为removeAll(set),其中O(N)为列表大小。


    有趣的是,N将是arrayList.removeAll(hashSet),其中O(N)是列表长度,但删除了相同的元素:

    N

    将是for (Iterator it = arrayList.iterator; it.hasNext(); ) { if (hashSet.contains(it.next())) { it.remove(); } } ,其中O(NM)是列表长度,N是设置大小。