java中foreach和iterator

java中foreach

入门

今天闲来无事,师父让我看一下,迭代器在一个循环里面连续两次iterator.remove()的问题,因为今天看一个离职人员的代码,里面写了这个。
我们看一下测试代码:

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (Integer value:list){
    logger.debug(value);
}
//输出
2020-08-07 09:58:12,323 DEBUG (com.huskyui.App:main) -1
2020-08-07 09:58:12,324 DEBUG (com.huskyui.App:main) -2
2020-08-07 09:58:12,325 DEBUG (com.huskyui.App:main) -3
2020-08-07 09:58:12,325 DEBUG (com.huskyui.App:main) -4

反编译文件

List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator var2 = list.iterator();
while(var2.hasNext()) {
    Integer value = (Integer)var2.next();
    logger.debug(value);
}
// 生成迭代器
iterator

迭代器里面的介绍是:_Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics._迭代器允许调用者在迭代期间使用定义良好的语义从基础集合中删除元素.

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator iterator = list.iterator();
logger.debug("Iterator 从前向后遍历:");
while (iterator.hasNext()){
    Integer value = (Integer)iterator.next();
    logger.debug(value);
}
// 增强版iterator listIterator

logger.debug("listIterator从前向后遍历");
ListIterator iterator1 = list.listIterator();
while (iterator1.hasNext()){
    Integer value = (Integer)iterator1.next();
    logger.debug(value);
}
logger.debug("listIterator从后向前遍历:");
while (iterator1.hasPrevious()){
    logger.debug(iterator1.previous());
}
/**
2020-08-07 11:07:44,832 DEBUG (com.huskyui.App:main) -Iterator 从前向后遍历:
2020-08-07 11:07:44,834 DEBUG (com.huskyui.App:main) -1
2020-08-07 11:07:44,834 DEBUG (com.huskyui.App:main) -2
2020-08-07 11:07:44,834 DEBUG (com.huskyui.App:main) -3
2020-08-07 11:07:44,834 DEBUG (com.huskyui.App:main) -4
2020-08-07 11:07:44,835 DEBUG (com.huskyui.App:main) -listIterator从前向后遍历
2020-08-07 11:07:44,835 DEBUG (com.huskyui.App:main) -1
2020-08-07 11:07:44,835 DEBUG (com.huskyui.App:main) -2
2020-08-07 11:07:44,837 DEBUG (com.huskyui.App:main) -3
2020-08-07 11:07:44,838 DEBUG (com.huskyui.App:main) -4
2020-08-07 11:07:44,838 DEBUG (com.huskyui.App:main) -listIterator从后向前遍历:
2020-08-07 11:07:44,838 DEBUG (com.huskyui.App:main) -4
2020-08-07 11:07:44,838 DEBUG (com.huskyui.App:main) -3
2020-08-07 11:07:44,839 DEBUG (com.huskyui.App:main) -2
2020-08-07 11:07:44,839 DEBUG (com.huskyui.App:main) -1
*/
经典出错
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        for (Integer value :list){
            System.out.println(value);
            if(value.equals(1)){
                list.remove(value);
            }
        }
// 反编译
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator iterator = list.iterator();
while (iterator.hasNext()){
    Integer value = (Integer)iterator.next();
    System.out.println(value);
    if(value.equals(1)){
        list.remove(value);
    }
}
// 出错
// 1
// 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.huskyui.App.main(App.java:24)
// 我们来看iterator在ArrayList的实现
private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}
		// cursor就是游标的大概意思,size是ArrayList的容量
        public boolean hasNext() {
            return cursor != size;
        }
		
        @SuppressWarnings("unchecked")
        public E next() {
            // 报错是在这里
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            // 给lastRet负责,有点pre节点的味道了
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                // 指向前一个节点
                cursor = lastRet;
                // lastRet赋初始值,在后续执行next()方法是可以重新赋值
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    	// 这个modCount是ArrAyList继承的AbstractList中的变量,记录这个arrayList的修改次数。譬如我们添加了4次,那么这个就是4
    	final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

为什么我们不能在遍历时,删除,因为arrayList的remove时,并没有修改exceptedModCount,而iterator却可以。

关于foreach两种方式

foreach支持1.实现了Iterator接口的2.数组
第一种,Iterator反编译后,就是使用Iterator迭代器来实现的
第二种,数组形式的foreach

int[] array = new int[]{1,2,3,4,5};
for (int num:array){
    System.out.println(num);
}
// 反编译后
int[] array = new int[]{1, 2, 3, 4, 5};
int[] var2 = array;
int var3 = array.length;

for(int var4 = 0; var4 < var3; ++var4) {
    int num = var2[var4];
    System.out.println(num);
}
参考

Java基础8:Iterator和foreach循环

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值