Java列表的.remove方法仅适用于每个循环内部的倒数第二个对象 [英] Java list's .remove method works only for second last object inside for each loop

查看:104
本文介绍了Java列表的.remove方法仅适用于每个循环内部的倒数第二个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 列表< String> li = new ArrayList<>(); 
li.add(a);
li.add(b);
li.add(c);
li.add(d);
li.add(e);
for(String str:li){
if(str.equalsIgnoreCase(d)){
li.remove(str); //删除列表中的第二个工作正常


code


但是,如果我尝试删除列表中的倒数第二,我得到ConcurrentModificationException。在阅读Oracle Certified Associate Java SE 7程序员学习指南2012的时候,我不得不注意到.remove()总是以删除列表中的倒数第二个为例。
<在列表中,添加或删除被视为修改。在你的情况下,你已经做了
5的修改(增加)。

'for each'循环的作用如下,


  1.它得到迭代器。 
2.检查hasNext()。




  public boolean hasNext )
{
return cursor!= size(); //光标初始为零。




lock $

3.如果是true,则获取下一个元素使用next()。



  public E next()
{
checkForComodification();
尝试{
E next = get(cursor);
lastRet = cursor ++;
下一个返回;
} catch(IndexOutOfBoundsException e){
checkForComodification();
抛出新的NoSuchElementException();



最终无效checkForComodification()
{
//最初modCount = expectedModCount(我们的情况5)
if(modCount != expectedModCount)
抛出新的ConcurrentModificationException();



$ b

重复步骤2和3直到hasNext()返回false。



如果我们从列表中删除一个元素,它的大小就会减小,并且modCount会增加。

如果我们删除元素,而迭代,modCount!= expectedModCount得到满意
和ConcurrentModificationException抛出。



但删除倒数第二个对象是奇怪的。让我们看看它是如何工作的。



最初,


cursor = 0 = size = 5 - > hasNext()成功,next()也成功
,无一例外。
cursor = 1 size = 5 - > hasNext()成功,next()也成功
没有例外。

cursor = 2 size = 5 - > hasNext()成功,next()也成功

cursor = 3 size = 5 - > hasNext()成功,next()也成功


在您的情况下,如果您删除d,大小会减少到4。 b


cursor = 4 size = 4 - > hasNext()不成功,next()被跳过
。在其他情况下,ConcurrentModificationException将抛出为modCount!= expectedModCount。



<在这种情况下,这种检查不会发生。



如果您在迭代时尝试打印元素,则只会打印四个条目。最后一个元素被跳过了。



希望我明白了。


I am seeing a weird behavior.

    List<String> li = new ArrayList<>();
    li.add("a");
    li.add("b");
    li.add("c");
    li.add("d");
    li.add("e");
    for(String str:li){
        if(str.equalsIgnoreCase("d")){
            li.remove(str);     //removing second last in list works fine
        }
    }

But if i try to remove any other than second last in the list, i get ConcurrentModificationException. It came to my attention while reading "Oracle Certified Associate Java SE 7 Programmer Study Guide 2012" which incorrectly assumes that .remove() always works with an example of removing the second last in the list.

解决方案

In a list, adding or removing is considered as a modification. In your case you have made 5 modifications(additions).

‘for each’ loop works as follows,

1.It gets the iterator.
2.Checks for hasNext().

public boolean hasNext() 
{
      return cursor != size(); // cursor is zero initially.
}

3.If true, gets the next element using next().

public E next() 
{
        checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
}

final void checkForComodification() 
{
    // Initially modCount = expectedModCount (our case 5)
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Repeats steps 2 and 3 till hasNext() returns false.

In case if we remove an element from the list , it’s size gets reduced and modCount is increased.

If we remove an element while iterating, modCount != expectedModCount get satisfied and ConcurrentModificationException is thrown.

But removal of second last object is weird. Lets see how it works in your case.

Initially,

cursor = 0 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 1 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 2 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 3 size = 5 --> hasNext() succeeds and next() also succeeds without exception.

In your case as you remove ‘d’ , size gets reduced to 4.

cursor = 4 size = 4 --> hasNext() does not succeed and next() is skipped.

In other cases, ConcurrentModificationException will be thrown as modCount != expectedModCount.

In this case, this check does not take place.

If you try to print your element while iterating, only four entries will be printed. Last element is skipped.

Hope I made clear.

这篇关于Java列表的.remove方法仅适用于每个循环内部的倒数第二个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆