Iterator traverses ArrayList

ArrayList common traversal methods
1, for loop traversal
2, enhanced for loop traversal
3, iterator traversal

The iterator is mainly used to traverse the collection. The underlying implementation of the enhanced for loop is also an iterator. ListIterator is a more powerful Iterator type. 1. It is only suitable for the traversal
of the List collection . 3. You can use the set method to replace the visited elements 4. You can use listIterator(n) to create an iterator pointing to index n from the beginning


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());
        }

Definition of Iterator interface

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

Key point one: remove() method. The collection itself also has a remove() method. It should be noted that when using an iterator to traverse the collection, add and remove are not supported on the collection itself. Looking at the source code of ArrayList.java, it is found that the next method in the implemented iterator interface will judge the number of collection modifications, and when it is greater than 0, an error will be reported.

As for why there is such a principle, it is because the following situation is avoided:
after the iterator is generated, the positions of the collection items corresponding to the iterator are determined. During the iteration process, when the iterator is ready to give the next item, but the item is deleted by the remove method of the Collection interface, or a new item is inserted in front of the item being traversed through the add method of the Collection interface, as long as the above situation occurs , it may cause problems with iterator traversal.
It is legal for an iterator to call its own remove method, since it can only remove objects that have just been iterated over.

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

Next method source code in ArrayList iterator interface

 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;
  

Key point 2: The next() method TODO is used multiple times after hasNext()

Guess you like

Origin blog.csdn.net/Misszhoudandan/article/details/130975063