首页 > 试题广场 >

list是一个ArrayList的对象,哪个选项的代码填到

[单选题]
list是一个ArrayList的对象,哪个选项的代码填到//todo delete处,可以在Iterator遍历的过程中正确并安全的删除一个list中保存的对象?()
Iterator it = list.iterator();
int index = 0;
while (it.hasNext())
{
    Object obj = it.next();
    if (needDelete(obj))  //needDelete返回boolean,决定是否要删除
    {
        //todo delete
    }
    index ++;
}

  • it.remove();
  • list.remove(obj);
  • list.remove(index);
  • list.remove(obj,index);
推荐
A
Iterator  支持从源集合中安全地删除对象,只需在 Iterator 上调用 remove() 即可。这样做的好处是可以避免 ConcurrentModifiedException ,当打开 Iterator 迭代集合时,同时又在对集合进行修改。有些集合不允许在迭代时删除或添加元素,但是调用 Iterator remove() 方法是个安全的做法。
编辑于 2015-01-26 16:36:05 回复(4)
答案:A
如果在循环的过程中调用集合的remove()方法,就会导致循环出错,例如:
for(int i=0;i<list.size();i++){
    list.remove(...);
}
循环过程中list.size()的大小变化了,就导致了错误。
所以,如果你想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法,因为它的remove()方法不仅会删除元素,还会维护一个标志,用来记录目前是不是可删除状态,例如,你不能连续两次调用它的remove()方法,调用之前至少有一次next()方法的调用。
发表于 2015-01-28 19:24:14 回复(12)

迭代器

发表于 2019-03-11 10:09:56 回复(0)
A
发表于 2015-01-10 20:09:58 回复(0)
源码是这么描述的:ArrayList 继承了 AbstractList, 其中AbstractList 中有个modCount 代表了集合修改的次数。在ArrayList的iterator方法中会判断 expectedModCount与 modCount是否相等,如果相等继续执行,不相等报错,只有iterator的remove方***在调用自身的remove之后让 expectedModCount与modCount再相等,所以是安全的。
发表于 2015-08-18 21:10:05 回复(8)
首先通过List接口的迭代器(Iterator)对list中的元素进行遍历,iterator是依赖于list存在的,遍历的时候,修改list的内容,但是iterator并不知道,java不允许这样的操作,会报ConcurrentModificationException(并发修改异常),直接使用iterator进行remove就没有问题;或者不使用iterator进行遍历,使用list的size方法和get方法结合进行遍历
发表于 2015-08-09 09:38:11 回复(2)
答案肯定是正确的,这里只说下上面讨论激烈的for循环删除问题,如果真想用,可以这样,既不出错,也能正确删除:
for(int i=0;i<list.size();i++){     list.remove(i);
       i--; }

发表于 2016-07-12 22:37:04 回复(5)
直接移除索引值会出现一个问题,假如原集合中的元素是0,1,2,3,这时我们把索引为1的元素移除,这时候集合中元素变为0,2,3,如果我们继续遍历下去要移除原集合中索引为3的元素,就会发现不存在下标为3的元素,从而造成下标越界异常
发表于 2018-05-15 17:06:37 回复(1)
Iterator 方法中remove()无参,支持从底层安全删除。
发表于 2015-11-24 22:11:30 回复(1)
Iterator  支持从源集合中安全地删除对象,只需在 Iterator 上调用 remove() 即可。这样做的好处是可以避免 ConcurrentModifiedException ,当打开 Iterator 迭代集合时,同时又在对集合进行修改。有些集合不允许在迭代时删除或添加元素,但是调用 Iterator 的remove() 方法是个安全的做法。
发表于 2021-10-31 22:35:48 回复(0)
2.2.1、ArrayList的Iterator实现

         在ArrayList内部首先是定义一个内部类Itr,该内部类实现Iterator接口,如下:

[java]   view plain copy print ? 派生到我的代码片
  1. private   class  Itr  implements  Iterator<E> {  
  2.     //do something   
  3. }  

         而ArrayList的iterator()方法实现:

[java]   view plain copy print ? 派生到我的代码片
  1. public  Iterator<E> iterator() {  
  2.         return   new  Itr();  
  3.     }  

         所以通过使用ArrayList.iterator()方法返回的是Itr()内部类,所以现在我们需要关心的就是Itr()内部类的实现:

在Itr内部定义了三个int型的变量:cursor、lastRet、expectedModCount。其中cursor表示下一个元素的索引位置,lastRet表示上一个元素的索引位置

[java]   view plain copy print ? 派生到我的代码片
  1. int  cursor;               
  2. int  lastRet = - 1 ;       
  3. int  expectedModCount = modCount;  

         从cursor、lastRet定义可以看出,lastRet一直比cursor少一所以hasNext()实现方法异常简单,只需要判断cursor和lastRet是否相等即可。

[java]   view plain copy print ? 派生到我的代码片
  1. public   boolean  hasNext() {  
  2.     return  cursor != size;  
  3. }  

         对于next()实现其实也是比较简单的,只要返回cursor索引位置处的元素即可,然后修改cursor、lastRet即可,

[java]   view plain copy print ? 派生到我的代码片
  1. public  E next() {   
  2.             checkForComodification();  
  3.             int  i = cursor;     //记录索引位置    
  4.             if  (i >= size)     //如果获取元素大于集合元素个数,则抛出异常   
  5.                 throw   new  NoSuchElementException();  
  6.             Object[] elementData = ArrayList.this .elementData;  
  7.             if  (i >= elementData.length)  
  8.                 throw   new  ConcurrentModificationException();  
  9.              cursor = i + 1 ;       //cursor + 1   
  10.             return  (E) elementData[lastRet = i];   //减少数据依赖cursor,有利于指令重排序lastRet + 1 且返回cursor处元素   
  11.         }  
发表于 2015-12-16 20:38:13 回复(0)
A

编辑于 2015-09-20 23:33:58 回复(1)
集合直接remove是会出问题的 , 注意就好了 , Iterator remove() 方法是安全的
发表于 2018-10-28 11:22:14 回复(0)
迭代器的原理个人觉得有点像指针
Iterator迭代器在迭代的时候如果调用集合的删除增加操作,会影响迭代器本身从而发生错误
而Iterator本身支持从原集合中安全的删除对象,所以调用迭代器Iterator的remove()方法时一个最安全的做法
发表于 2018-10-25 19:10:58 回复(0)
迭代器在迭代过程中要注意的事项:
  1. 迭代器在迭代过程中不允许使用集合对象改变集合的元素个数。否则会报出:ConcurrentModificationException,即并发修改异常。
  2. 在迭代过程中如果需要改变集合中的元素个数,只能使用迭代器的方法去改变。如add()方法和remove()方法。
发表于 2020-06-11 15:58:52 回复(0)
如果在循环的过程中调用集合的remove()方法,就会导致循环出错,例如:
for(int i=0;i<list.size();i++){
    list.remove(...);
}
循环过程中list.size()的大小变化了,就导致了错误。
所以,如果你想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法,因为它的remove()方法不仅会删除元素,还会维护一个标志,用来记录目前是不是可删除状态,例如,你不能连续两次调用它的remove()方法,调用之前至少有一次next()方法的调用。
发表于 2017-08-27 10:44:47 回复(0)
list.remove(index)这种方式也是可以的。因为遍历的是iterator,而iterator已经赋值,list的变动不会影响到它。
发表于 2015-03-24 10:09:54 回复(0)
A
发表于 2015-01-10 23:01:23 回复(0)
这考的就是并发修改异常,如果使用集合自己的删除方法,集合的长度,数据位置就发生了变化而 迭代器里的集合却还是未删除之前的集合,跌倒 器继续按照以前的集合顺序遍历,发生并发修改异常。 使用迭代器里的删除方法,跌倒器本身跟新了,集合也变化了
发表于 2021-03-21 12:58:28 回复(0)
不能有remove里不能有索引参数是因为循环的时候数组长度在变化,有参数会导致不安全的删除?
发表于 2021-03-02 22:10:21 回复(0)
abstractlist对象,有个属性modcount,protected修饰。假如用list.remove会使之加一。 后续迭代器next方法获取数据,比较expectedmodcount 和 modcount的值是否一致。(expectedmodcount值在创建迭代器时就已经身复制了count),因此后续list的操作会导致抛异常。
发表于 2021-02-21 23:46:00 回复(0)