面试题目一:请问如下代码输出结果是什么?
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("helloworld");
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
System.out.println(list);
}
答案:会输出[world]。该题目考察的是集合底层是数组,对于集合的remove操作,底层是将被删除元素之后的所有元素往前移动一个位置。
面试题目二:问如下程序能否正常执行?并说明为什么?
public class IteratorTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("helloworld");
for (Iterator<String> ite = list.iterator(); ite.hasNext();) {
String next = ite.next();
list.remove(next);
}
}
}
答案:该程序执行后会抛出ConcurrentModificationException,当使用迭代器对ArrayList进行迭代的时候,不能在迭代中使用list.remove方法来删除元素,否则会抛出ConcurrentModificationException异常。本质原因是当调用ite.iterator()
方法后,会生成一个Iterator接口的实例对象,该对象内部维护一个变量ExpectedModCount
,该变量的初始值是集合的modCount,在迭代进行中使用集合的remove方法的时候会导致modCount值+1而ExpectedModCount还是原先的值,调用ite.next()
方法内部会对ExpectedModCount
与modCount
进行比较操作,如果不等就会抛出ConcurrentModficationException。
面试题目三:如下程序能否正常执行
public class IteratorTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("helloworld");
for (Iterator<String> ite = list.iterator(); ite.hasNext();) {
String next = ite.next();
ite.remove(); //关键看此处
}
System.out.println(list.size());
}
}
答案:能够正常执行, 在迭代过程中虽然不能使用集合ArrayList的remove操作或者add操作(会致使modCount改变的操作),但是使用迭代器自带的remove方法是可以的,ite.remove
内部会对ExceptedModCount
的值进行修正,所以在调用ite.next()
方法的时候,ExceptedModCount == ModCount
的判断结果为true,故不会导致抛出ConCurrentModificationException
总结:
- 不使用迭代器对ArrayList进行迭代的时候,可以使用remove等操作,原因是ArrayList并没有对modCount进行判断
- 使用迭代器对ArrayList进行迭代的时候,不能使用ArrayList的remove等会致使modCount改变的操作,否则在调用迭代器的
next
方法时会抛出ConcurrentModificationException
- 使用迭代器对ArrayList进行迭代的时候,可以使用迭代器自带的remove操作,因为Iterator中的remove方法会对
ExpectedModCount
的值进行修正,在调用迭代器的next
方法时ExpectedModCount
与modCount
的比较结果为true,故不会导致抛出ConcurrentModificationException
异常。
网友评论