循环下标_for循环用了这么多次,你还不懂吗?

for循环用了这么多次,你还不懂吗?

❝ ❝

当我们自信满满的在for循环中add/remove时,常常会出现一些意想不到的结果。

❞ ❞

普通for循环中删除

List testList = Lists.newArrayList("one", "two", "three", "four", "five", "six");// for => 无异常但结果错误for (int i = 0; i < testList.size(); i++) {    String s = testList.get(i); if("four".equals(s)) { testList.remove(i); } else { System.out.println(testList.get(i)); }}

运行结果:

one
twothreesix

可以发现显然不是我们想要的结果,那为什么删除"four","five"也跟着消失了呢?画了一张图帮助大家理解:

「原因:」 当for循环遍历到"four"时,i = 3,这时删除元素"four",n++(n此时为4) 进入下次循环,由于"four"被删除,"four"后面的元素向前移动,此时"five"和"six"的下标分别为3、4,所以程序跳过了"five",直接打印了"six"。如果我们在remove元素的同时将下标 n 减 1 或者从列表尾部往头部遍历即可解决问题,如下代码所示:

List testList = Lists.newArrayList("one", "two", "three", "four", "five", "six");// remove元素的同时将下标 n 减 1for (int i = 0; i < testList.size(); i++) {    String s = testList.get(i); if("four".equals(s)) { testList.remove(i); i--; } else { System.out.println(testList.get(i)); }}// 从列表尾部往头部遍历for (int i = testList.size() - 1; i >= 0; i--) { String s = testList.get(i); if("four".equals(s)) { testList.remove(i); } else { System.out.println(testList.get(i)); }}

增强for循环中删除

List testList = Lists.newArrayList("one", "two", "three", "four", "five", "six");// for-each => Exception in thread "main" java.util.ConcurrentModificationExceptionint n = 0;for (String s : testList) { if(n++ == 3) { testList.remove(n); }}

运行结果:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList$Itr.next(ArrayList.java:859) at com.ywh.test.TestRemove.main(TestRemove.java:30)

「原因:」 foreach方式遍历元素的时候,是生成iterator,然后使用iterator遍历。在生成iterator的时候,会保存一个expectedModCount参数,这个是生成iterator的时候List中修改元素的次数。如果你在遍历过程中删除元素,List中modCount就会变化,如果这个modCountexceptedModCount不一致,就会抛出异常。这个是为了安全的考虑。如果使用iterator遍历过程中,使用List修改了元素,可能会出现不正常的现象。如果使用iterator的remove方法则会正常,因为iterator的remove方法会在内部调用List的remove方法,但是会修改excepedModCount的值,因此会正常运行,源码如下所示:

public void remove() {
if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); }}

使用迭代器remove代码如下所示:

Iterator iterator = testList.iterator();while (iterator.hasNext()) {    String next = iterator.next();    if(next.equals("four")) { iterator.remove(); }}

点击关注不迷路80439a83e0e760fe62c7441276310815.png80439a83e0e760fe62c7441276310815.png80439a83e0e760fe62c7441276310815.png更多技术分享、优质文章尽在作者的公众号:「程序员的小黑屋」,长按下图订阅,第一时间获取更新。↓↓↓

014463d6c42a58b2e1acca7a7fd68042.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值