I heard wechat search “Java fish boy” will change strong oh!

This article is in the JavaStarter, which has my complete Java series, study or interview can see oh

What is the iterator pattern

Of the 23 design patterns, the iterator pattern is probably the easiest one for programmers to understand because it is often used in everyday development. Take the most common loop:

for(int i=0; i<arr.length; i++){ System.out.print(arr[i]); }Copy the code

The above code iterates through the array by adding 1 to the subscripts of arR one by one.

The iterator pattern, however, is a design pattern that allows sequential access to the elements of a collection object without relying on the internal representation of the object.

(2) Roles in the iterator pattern

There are four main roles in the iterator pattern:

Iterator: Defines an interface for accessing and traversing the elements of a collection, typically including the next() and hasNext() methods.

ConcreteIterator: This role is used to implement the iterator interface, where the core iterator traversal logic is implemented.

3. Aggregate: The Aggregate interface defines the interface method for creating iterators. The iterator method is defined internally.

ConcreteAggregate: This role implements the aggregate interface by creating the concrete Iterator role.

It doesn’t matter if you’re a little confused by this, but I’m going to do it in code.

(3) The code implementation of the iterator pattern

First of all, let’s talk about the scene of this code, which defines the class of a classroom, and defines the class of students, and realizes the function of traversing the students in the classroom.

The code list is as follows:

interface Aggregate: Collection interfaceinterface Iterator: iterator interfaceclass Classroom: classroom class, implement set interface, belong to the specific setclass ClassroomIterator: classroom iterators, implementing the iterator interface, belong to concrete iteratorsclass StudentClass: studentsCopy the code

First define the two interface roles in the iterator pattern:

public interface Aggregate {
    Iterator iterator(a);
}

public interface Iterator {
    boolean hasNext(a);
    Object next(a);
}
Copy the code

Then define the class of students:

@Data
@AllArgsConstructor
public class Student {
    private String name;
}
Copy the code

Next we define the classroom class, in which we define the Student collection, and the current collection length and maximum length. We also implement the iterator method of Aggregate, which returns an iterator object. This iterator object is provided by ClassroomIterator

public class Classroom implements Aggregate{
    private Student[] students;
    private int length=0;
    private int maxSize;

    public Classroom(int maxSize){
        this.maxSize=maxSize;
        students=new Student[maxSize];
    }

    public Student getStudent(int index){
        return students[index];
    }

    public boolean addStudent(Student student){
        if (length>=maxSize){
            return false;
        }
        this.students[length]=student;
        length++;
        return true;
    }

    public int getLength(a){
        return this.length;
    }

    @Override
    public Iterator iterator(a) {
        return new ClassroomIterator(this); }}Copy the code

Finally, there is the ClassroomIterator object. ClassroomIterator belongs to the implementation of the iterator, which needs to implement the hasNext method and the next method

public class ClassroomIterator implements Iterator{
    private Classroom classroom;
    private int index;

    public ClassroomIterator(Classroom classroom){
        this.classroom=classroom;
        this.index=0;
    }
    @Override
    public boolean hasNext(a) {
        if (this.index<classroom.getLength()){
            return true;
        }
        return false;
    }

    @Override
    public Object next(a) {
        Student student = classroom.getStudent(index);
        index++;
        returnstudent; }}Copy the code

Finally, we can use the iterator to iterate through the classroom object directly:

public static void main(String[] args) {
    Classroom classroom=new Classroom(3);
    classroom.addStudent(new Student("Zhang"));
    classroom.addStudent(new Student("Bill"));
    classroom.addStudent(new Student("Fifty"));
    Iterator iterator = classroom.iterator();
    while(iterator.hasNext()){ Student next = (Student) iterator.next(); System.out.println(next.getName()); }}Copy the code

(4) The role of the iterator pattern

Now, a lot of people here might wonder, well, if I wrote a bunch of them, wouldn’t it be easier to use a loop? The most important function of the iterator pattern is to separate the iterator from the actual implementation. For example, in the above test method, we only used the iterator object during the iterator, not classroom, which means that we can fully reuse the code to implement the iterator later.

On the other hand, if we find that we use an array to store students in Classroom, we can’t expand it later, and we want to change to a List collection, we only need to change the two specific implementation roles of ClassroomIterator and Classroom. Without making any changes to the code in use, just as the above test traverses the code without any changes. If you use a for loop or a while loop, that means you need to change the code everywhere you use the loop.

(five) the application of iterator pattern in the source code

The best practice for Iterator patterns is the design of the Iterator interface in the JDK

public interface Iterator<E> {
    boolean hasNext(a);
    E next(a);
    default void remove(a) {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while(hasNext()) action.accept(next()); }}Copy the code

The most common implementation of a specific iterator is a collection. Look at the source code for any ArrayList:

The overall implementation logic is essentially similar to what we implemented above.

(5) Summary

As you learn about design patterns, you begin to understand why you want to design interfaces instead of just writing classes. Using concrete classes to address individual requirements can lead to strong dependencies between classes that are difficult to split up and reuse as components. I’m fish Boy, see you next time!