java遍历删除需要注意的几点

看几段代码:

  第一部分:

1      List<Integer> list = new ArrayList<Integer>(Arrays.<Integer> asList(1, 2, 3, 5));
2         for (Integer in : list) {
3             if (in == 3) {
4                 list.remove(in);
5             }
6         }   

  第二部分:

1      List<Integer> list2 = new ArrayList<Integer>(Arrays.<Integer> asList(1, 2, 3, 5, 6));
2         for (Integer in : list2) {
3             if (in == 3) {
4                 list2.remove(in);
5             }
6         }

  第三部分:

1      List<Integer> list3 = new ArrayList<Integer>(Arrays.<Integer> asList(1, 2, 3, 5, 6));
2         for (Iterator<Integer> iterator = list3.iterator(); iterator.hasNext();) {
3             Integer integer = (Integer) iterator.next();
4             if (integer == 3) {
5                 iterator.remove();
6             }
7         }

  第四部分:

1      List<Integer> list4 = new ArrayList<Integer>(Arrays.<Integer> asList(1, 2, 3, 5, 6));
2         for (Iterator<Integer> iterator = list4.iterator(); iterator.hasNext();) {
3             Integer integer = (Integer) iterator.next();
4             if (integer == 3) {
5                 list4.remove(integer);
6             }
7         }

  第一部分没有报错,但是有潜在问题,

  第二部分:java.util.ConcurrentModificationException

  第三部分:没有问题,正确删除方式。

  第四部分:java.util.ConcurrentModificationException

  如果从一个ArrayList获得了一个iterator后,通过这个iterator的add和remove方法之外的途径修改了ArrayList的内容,那么这个iterator就会迅速失效。一个ArrayList内部的iterator中,next/previous/add/set/remove等会改变ArrayList或iterator状态的方法都会调用checkForComodification方法来检查是否发生了预期之外的修改。如果有这样的修改,则抛出异常使该iterator不再起作用。 

  第一部分删除时,该list的size减少了1,正好等于for-each循环所使用的iterator的cursor的值。于是在删除之后,回到hasNext()的检查就通不过了,退出循环。这个情况下list的最后一个元素并没有被遍历;其it.next()方法没有被调用,因而没有出现ConcurrentModificationException。

  第二部分删除时。list的size仍然大于iterator中cursor的值,那么循环会继续,在调用到it.next()的时候就抛出异常了。

  第四部分删除时,调用了原list4的remove(object),而不是iterator的remover()方法 ,混合使用后,出现的情况和第二部分一致,所以报了同样的错误。

  一般在开发过程中,遍历删除往往从后往前遍历:

1 for(int j=list.size()-1;j>=0;j--){
2      list.remove(j);
3 }

  另外,也可以从前往后遍历:

1 for (int i = 0; i < list.size(); i++) {
2      list.remove(i);
3      i--;
4 }

  往往在全部删除时直接使用api,list.removeAll();

  

参考:http://www.iteye.com/problems/9592

   http://guojuanjun.blog.51cto.com/277646/1348450/

遍历效率:

  RandomAccess接口是List 实现所使用的标记接口,用来表明其支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。

在对List特别的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是SequenceAccess(如LinkedList),因为适合RandomAccess List的遍历算法,用在SequenceAccess List上就差别很大,即对于实现了RandomAccess接口的类实例而言,此循环

for (int i=0, i<list.size(); i++)
list.get(i);

的运行速度要快于以下循环:

for (Iterator i=list.iterator(); i.hasNext(); )
i.next();

   下标遍历要比增强for循环的效率高  

posted @ 2014-12-23 20:37  normalpers  阅读(181)  评论(0)    收藏  举报