迭代器遍历ArrayList

ArrayList 常用遍历方法
1、for 循环遍历
2、增强 for 循环遍历
3、迭代器遍历

迭代器主要用来遍历集合,增强 for 循环底层实现也是迭代器,ListIterator 是更强大的的 Iterator 的字类型
1、只适合于 List 集合的遍历
2、它可以前后双向移动(Iterator 只能向后)
3、可以使用 set 方法替换访问过的元素
4、可以使用 listIterator(n) 创建一个一开始就指向索引为 n 的迭代器

public static void practice5() {
        ArrayList<String> practiceStr = new ArrayList<>();
        Collections.addAll(practiceStr, "apple", "cat", "dog", "big");
        log.info("for 循环遍历");
        for(int i= 0;i<practiceStr.size();i++){
            log.info(practiceStr.get(i));
        }
        log.info("增强 for 循环遍历");
        for(String element : practiceStr){
            log.info(element);
        }
        log.info("迭代器遍历");
        Iterator<String> iterator = practiceStr.iterator();
        while (iterator.hasNext()){
            log.info(iterator.next());
        }
    }
    log.info("list迭代器遍历");
        ListIterator<String> iteratorList = practiceStr.listIterator();
        while (iteratorList.hasNext()){
            log.info("\n");
            log.info("{}",iteratorList.nextIndex());
            log.info(iteratorList.next());
            log.info("{}",iteratorList.nextIndex());
            log.info("{}",iteratorList.previousIndex());
        }
  ListIterator<String> iteratorList1 = practiceStr.listIterator(3);
        while (iteratorLis1t.hasNext()){
            log.info("\n");
            log.info("{}",iteratorList1.nextIndex());
            log.info(iteratorList1.next());
            log.info("{}",iteratorList1.nextIndex());
            log.info("{}",iteratorList1.previousIndex());
        }

Iterator接口的定义

public interface Iterator<E> {
boolean hasNext();
E next();
//下面defalut修饰符,java8新增,用于修饰在接口中已经被具体实现方法
default void remove() {
throw new UnsupportedOperationException("remove");
}
}

重点一: remove() 方法。集合自身也有remove()方法,需要注意的是使用迭代器遍历集合时,不支持对集合本身进行 add 和 remove。查看ArrayList.java源码发现,其中实现的迭代器接口中的 next 方法中会判断集合修改次数,大于 0 时就报错。

至于为什么有这样一个原则,是因为避免以下情况出现:
迭代器生成后,迭代器对应的集合项的位置都确定了。迭代过程中当迭代器准备给出下一项时,但该项却被Collection接口的remove方法删除,或者有一个新的项通过Collection接口的add方法插入到正在遍历项的前面,只要上述情况出现,就可能导致迭代器遍历出现问题。
迭代器调用它自己的remove方法是合法的,因为它只能删除刚才已经迭代过的对象。

while (iterator.hasNext()){
            String curElement = iterator.next();
            log.info(curElement);
            if(curElement.equals("cat")){
                iterator.remove();
            }
        }
// 使用迭代器的remove正常
while (iterator.hasNext()){
            String curElement = iterator.next();
            log.info(curElement);
            if(curElement.equals("apple")){
                practiceStr.remove("apple");
            }
        }
// 使用集合的remove报错:java.util.ConcurrentModificationException

ArrayList 迭代器接口中的 next 方法源码

 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;
            return (E) elementData[lastRet = i];
        }
        
 final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
        
    protected transient int modCount = 0;
    int expectedModCount = modCount;
  

重点二:一次hasNext()后使用了多次next()方法 TODO

猜你喜欢

转载自blog.csdn.net/Misszhoudandan/article/details/130975063