Iterator written test questions, see if you can?

A child was recently preparing for a job change after the new year, but encountered a problem and found it to be an incredible written test. Then I posted this question to the technical group, and found that many people didn't know it, and many of them were just guessing. It feels necessary to write an article to talk about it.

A child was recently preparing for a job change after the new year, but encountered a problem and found it to be an incredible written test. Then I posted this question to the technical group, and found that many people didn't know it, and many of them were just guessing. It feels necessary to write an article to talk about it.
Iterator written test questions, see if you can?  Iterator written test questions, see if you can?

Iterator written test questions, see if you can?  Iterator written test questions, see if you can?
Strange written test questions Read the following code, please write the output of this code:

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.*; 
 
public class Test { 
    public static void main(String[] args) { 
 
        List list = new ArrayList<>(); 
        list.add("1"); 
        list.add("2"); 
        list.add("3"); 
        Iterator iterator = list.iterator(); 
        while (iterator.hasNext()) { 
            String str = (String) iterator.next(); 
            if (str.equals("2")) { 
                iterator.remove(); 
            } 
        } 
        while (iterator.hasNext()) { 
            System.out.println(iterator.next()); 
        } 
        System.out.println("4"); 
    } 
} 

The answer he wrote is:

1 
3 
4 

The strange thing is that you send this question to people around you and ask them to answer the output of this interview question. Many people say this result. Can't you try.

The answer is obviously wrong, because the iterator.hasNext()==false in the first while will come to the second while, the same Iterator object, adjust iterator.hasNext()==false before, and then judge Isn’t the result the same one time?,

So the second while is judged to be false, and it will not traverse the iterator anymore. From this we can see that the ontology answer is:4. ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

Let's analyze why the specific bottom layer is implemented.

What is iterator here?

The iterator is a pattern, and its design pattern can be seen in detail. It can separate the traversal behavior of the sequence type data structure from the traversed object, that is, we don't need to care about what the underlying structure of the sequence looks like. As long as you get this object, you can use an iterator to traverse the object's internal
Iterable. The collection object that implements this interface supports iteration and can be iterated. This can be used in conjunction with foreach ~
Iterator Iterator, an object that provides an iteration mechanism, and how to iterate is specified by this Iterator interface.
Iterator description

public interface Iterator {  
    //每次next之前,先调用此方法探测是否迭代到终点 
    boolean hasNext(); 
    //返回当前迭代元素 ,同时,迭代游标后移 
    E next();  
    /*删除最近一次已近迭代出出去的那个元素。 
     只有当next执行完后,才能调用remove函数。 
     比如你要删除第一个元素,不能直接调用 remove()   而要先next一下( ); 
     在没有先调用next 就调用remove方法是会抛出异常的。 
     这个和MySQL中的ResultSet很类似 
    */ 
    default void remove() { 
        throw new UnsupportedOperationException("remove"); 
    }  
    default void forEachRemaining(Consumer action) { 
        Objects.requireNonNull(action); 
        while (hasNext()) 
            action.accept(next()); 
    } 
} 

The implementation class here is the inner class Itr of ArrayList.

private class Itr implements Iterator { 
        int cursor;       // index of next element to return 
        int lastRet = -1; // index of last element returned; -1 if no such 
        //modCountshi ArrayList中的属性,当添加或删除的时候moCount值会增加或者减少 
        //这里主要是给fail-fast使用,避免一遍在遍历,一遍正在修改导致数据出错 
        //此列表在结构上被修改的次数。结构修改是指改变结构尺寸的修改列表, 
        //或者以这样的方式对其进行扰动,进步可能会产生错误的结果。 
        int expectedModCount = modCount; 
         
        public boolean hasNext() { 
            //cursor初始值为0,没掉一次next方法就+1 
            //size是ArrayList的大小 
            return cursor != size; 
        } 
 
        @SuppressWarnings("unchecked") 
        public E next() { 
            checkForComodification(); 
            int i = cursor; 
            if (i >= size) 
                throw new NoSuchElementException(); 
            //把ArrayList中的数组赋给elementData 
            Object[] elementData = ArrayList.this.elementData; 
            if (i >= elementData.length) 
                throw new ConcurrentModificationException(); 
            //每调用一次next方法,游标就加1 
            //cursor=lastRet+1 
            cursor = i + 1; 
            //返回ArrayList中的元素 
            return (E) elementData[lastRet = i]; 
        } 
 
        public void remove() { 
            if (lastRet < 0) 
                throw new IllegalStateException(); 
            checkForComodification(); 
 
            try { 
                //调用ArrayList中remove方法,溢出该元素 
                ArrayList.this.remove(lastRet); 
                //cursor=lastRet+1, 
                //所以此时相当于cursor=cursor-1 
                cursor = lastRet; 
                lastRet = -1; 
                expectedModCount = modCount; 
            } catch (IndexOutOfBoundsException ex) { 
                throw new ConcurrentModificationException(); 
            } 
        } 
        final void checkForComodification() { 
            if (modCount != expectedModCount) 
                throw new ConcurrentModificationException(); 
        } 
} 

Back to the above topic:

The first iterator.hasNext()

1st cycle

In the hasNext method: cursor==0, size==3, so cursor != size returns true.
In the next method: cursor=0+1. "1" is returned.

2nd cycle

In the hasNext method: cursor==1, size==3, so cursor != size returns true.
In the next method: cursor=1+1. "2" is returned.
In the remove method: cursor==cursor-1==2-1=1, the "2" in the ArrayList is deleted, so size==2.

3rd cycle

In the hasNext method: cursor==1, size==2, then cursor != size returns true.
In the next method: cursor=1+1==2; returns "3".

4th cycle

In the hasNext method: cursor==2, size==2, then cursor != size returns false.
The second iterator.hasNext()

In the hasNext method: cursor==2, size==2, so cursor != size returns false.

Therefore, only "4" is output at the end, that is, the answer is 4.

Iterator with generics

Iterator can return such an Iterator object to any implementation class in the collection class. Can be applied to any class.
Because the types of objects that can be loaded into the collection classes (List, Set, etc.) are uncertain. When they are taken out of the collection, they are all of the Object type. When used, they need to be forced to transform. This will be very troublesome. Using generics is to advance Tell the collection to determine the type of collection to be loaded, so that it can be used directly without displaying type conversion. Very convenient.

The relationship between foreach and Iterator

for each is used to process each element in the collection without considering the collection subscript. Just to make it easy to use Iterator. But when deleting, the difference is that in remove, calling the collection remove in the loop will cause the original collection to change and cause an error, and the iterator's remove method should be used.

Comparison of using for loop or iterator

ArrayList is faster for random access, while the get() method in the for loop uses random access. Therefore, in ArrayList, the for loop is faster and the
LinkedList is faster for sequential access. Next( in iterator ) Method, which is the sequential access method, so in LinkedList, iterator is used to
analyze the data structure quickly . The for loop is suitable for accessing sequential structures, and the specified elements can be quickly obtained according to the subscript. And Iterator is suitable for accessing chained structures , Because the iterator is positioned by next() and Pre(). You can access the collection without order.
The advantage of using Iterator is that you can use the same way to traverse the elements in the collection, regardless of the internal implementation of the collection class (as long as It implements the java.lang.Iterable interface). If you use Iterator to traverse the elements in the collection, once you no longer use List and use Set to organize data, the code for traversing the elements does not need to be modified. If you use for to traverse, then All algorithms for traversing this set have to be adjusted accordingly, because List is ordered, Set is unordered, and the structure is different, and their access algorithms are different. (It still shows that traversal is separated from the set itself).

to sum up

The iterated elements are all copies of the original collection elements.
The elements stored in the Java collection are essentially references to objects, not the objects themselves.
The iterated object is also a copy of the reference, and the result is still a reference. Then if the elements saved in the collection are of variable type, then the objects in the original collection can be modified through the iterated elements.

Guess you like

Origin blog.csdn.net/yaxuan88521/article/details/113829827