Java iteration Interface: Iterator, ListIterator and Spliterator

1 Introduction

When we use foror whileloop to iterate over the elements of a collection, Iteratorit allows us to not worry about the index position, even let us not just through a collection, but also can change it. For example, if you want to delete the element cycle, the forcycle is not necessarily always possible.

Combined with a custom iterator, we can iterate more complex objects, as well as forward and backward, and know how to make use of its advantages will become very clear.

This article will discuss in depth how to use Iteratorand Iterableinterface.

2. Iterator()

IteratorInterface is used to set the iteration element List( , Setor Map). It is used to retrieve elements one by one, and performs operations when required for each element.

The following method is used to traverse the set of operations performed:

  • .hasNext(): If you have not reached the end of the collection is returned true, otherwisefalse
  • .next(): Returns the next element in the collection
  • .remove(): The last element is removed from the collection iterator returned
  • .forEachRemaining(): In order to perform a given operation is set in each of the remaining element

First, because the iterator for a collection, let's do a simple contains several elements ArrayList:

List<String> avengers = new ArrayList<>();

// Now lets add some Avengers to the list
avengers.add("Ant-Man");
avengers.add("Black Widow");
avengers.add("Captain America");
avengers.add("Doctor Strange");

We can use a simple loop to iterate this collection:

System.out.println("Simple loop example:\n");
for (int i = 0; i < avengers.size(); i++) {
    System.out.println(avengers.get(i));
}

However, we would like to explore the iterator:

System.out.println("\nIterator Example:\n");

// First we make an Iterator by calling 
// the .iterator() method on the collection
Iterator<String> avengersIterator = avengers.iterator();

// And now we use .hasNext() and .next() to go through it
while (avengersIterator.hasNext()) {
    System.out.println(avengersIterator.next());
}

If we want this ArrayListto delete an element, what would happen? Let's try using a regular forcycle:

System.out.println("Simple loop example:\n");
for (int i = 0; i < avengers.size(); i++) {
    if (avengers.get(i).equals("Doctor Strange")) {
        avengers.remove(i);
    }
    System.out.println(avengers.get(i));
}

We will receive a nasty IndexOutOfBoundsException:

Simple loop example:

Ant-Man
Black Widow
Captain America
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3

This change is significant in its size when iterating over collections, enhance forcirculation, too:

System.out.println("Simple loop example:\n");
for (String avenger : avengers) {
    if (avenger.equals("Doctor Strange")) {
        avengers.remove(avenger);
    }
    System.out.println(avenger);
}

Once again, we received another exception:

Simple loop example:

Ant-Man
Black Widow
Captain America
Doctor Strange
Exception in thread "main" java.util.ConcurrentModificationException

Then iterator comes in handy, it acts as a middleman, remove elements from the collection, while ensuring that traverse continue as planned:

Iterator<String> avengersIterator = avengers.iterator();
while (avengersIterator.hasNext()) {
    String avenger = avengersIterator.next();

    // First we must find the element we wish to remove
    if (avenger.equals("Ant-Man")) {
        // This will remove "Ant-Man" from the original
        // collection, in this case a List
        avengersIterator.remove();
    }
}

This is to ensure the safe way to remove elements while traversing the collection.

And confirm whether the element has been deleted:

// We can also use the helper method .forEachRemaining()
System.out.println("For Each Remaining Example:\n");
Iterator<String> avengersIteratorForEach = avengers.iterator();

// This will apply System.out::println to all elements in the collection
avengersIteratorForEach.forEachRemaining(System.out::println);

Output is as follows:

For Each Remaining Example:

Black Widow
Captain America
Doctor Strange

As you can see, the people have ants from 复仇者联盟the list of deleted.

2.1. ListIterator ()

ListIteratorInherited from the Iteratorinterface. In only Listcarried out on the use, you can two-way iterative, which means you can iterate from front to back or back to front. It also does not current element, because the cursor is always placed Listbetween the two elements, so we use .previous()or .next()access the elements.

IteratorAnd ListIteratorWhat is the difference between?

First of all, Iteratorit can be used for any set of - List, Map, Queue, Setand the like.

ListIteratorCan only be applied List, by adding this limitation, ListIteratorin terms of the method can be more specific, and therefore, we have introduced many new ways that they can help us to modify it while traversing.

If you are working Listto achieve ( ArrayList, LinkedListetc.), then use the ListIteratormore desirable number.

Here's how you might use:

  • .add(E e): Add elements to the List.
  • .remove(): Remove from the List .next()or .previous()the last element returned.
  • .set(E e): Use the specified element to cover the List .next()or .previous()the last element returned.
  • .hasNext(): If you have not reached the end of List Returns trueotherwise false.
  • .next(): Returns the next element List.
  • .nextIndex(): Returns the index of the next element.
  • .hasPrevious(): If you have not yet reached the beginning of the List, then returns trueotherwise false.
  • .previous(): Returns the previous element of List.
  • .previousIndex(): Returns the index of an element.

Again, let's use some elements constitute a ArrayList:

ArrayList<String> defenders = new ArrayList<>();

defenders.add("Daredevil");
defenders.add("Luke Cage");
defenders.add("Jessica Jones");
defenders.add("Iron Fist");

Let us use ListIteratorto traverse the List and print its elements:

ListIterator listIterator = defenders.listIterator(); 
  
System.out.println("Original contents of our List:\n");
while (listIterator.hasNext()) 
    System.out.print(listIterator.next() + System.lineSeparator()); 

Obviously, it works the Iteratorsame. Output is as follows:

Original contents of our List: 

Daredevil
Luke Cage
Jessica Jones
Iron Fist

Now, let's try to modify some elements:

System.out.println("Modified contents of our List:\n");

// Now let's make a ListIterator and modify the elements
ListIterator defendersListIterator = defenders.listIterator();

while (defendersListIterator.hasNext()) {
    Object element = defendersListIterator.next();
    defendersListIterator.set("The Mighty Defender: " + element);
}

List of print now, then get the following results:

Modified contents of our List:

The Mighty Defender: Daredevil
The Mighty Defender: Luke Cage
The Mighty Defender: Jessica Jones
The Mighty Defender: Iron Fist

Now, let's go through the list backwards, just as we can ListIteratordo it:

System.out.println("Modified List backwards:\n");
while (defendersListIterator.hasPrevious()) {
    System.out.println(defendersListIterator.previous());
}

Output is as follows:

Modified List backwards:

The Mighty Defender: Iron Fist
The Mighty Defender: Jessica Jones
The Mighty Defender: Luke Cage
The Mighty Defender: Daredevil

3. Spliterator()

SpliteratorThe interface is functionally Iteratoridentical. You may never need to use directly Spliterator, but let's move on to some use cases.

However, you should be familiar with Java Streams and the Lambda Expressions in the Java .

Although we will list Spliteratorall the methods have, but Spliteratorall the work interface is beyond the scope of this article. Through an example we will discuss Spliteratorhow to use the more efficient parallelized traverse we can decompose Stream.

We deal Spliteratormethod is used when:

  • .characteristics()

    : As having returned to the Spliterator

    int

    Eigenvalues. These include:

    • ORDERED
    • DISTINCT
    • SORTED
    • SIZED
    • CONCURRENT
    • IMMUTABLE
    • NONNULL
    • SUBSIZED
  • .estimateSize(): Return to traverse as longan estimate of the value of the number of elements encountered, if unable to return is returned long.MAX_VALUE.

  • .forEachRemaining(E e): In order to set each of the remaining element to perform a given operation.

  • .getComparator(): If the Spliteratorsource is made Comparator, it will return sorted Comparator.

  • .getExactSizeIfKnown(): If the size is known then returns .estimateSize()otherwise -1.

  • .hasCharacteristics(int characteristics): If this Spliteratoris .characteristics()containing all the given characteristics is returned true.

  • .tryAdvance(E e): If there are remaining elements, to perform a given operation on its return true, otherwise false.

  • .trySplit(): If this Spliteratorcan be partitioned, it returns a Spliteratorcovering element, when returning from this method, this will not be Spliteratorcovered.

As usual, let's start with a simple ArrayListstart:

List<String> mutants = new ArrayList<>();

mutants.add("Professor X");
mutants.add("Magneto");
mutants.add("Storm");
mutants.add("Jean Grey");
mutants.add("Wolverine");
mutants.add("Mystique");

Now, we need to Spliteratorbe applied Stream. Fortunately, due to the Collections framework, it is easy ArrayListand Streamconvert between:

// Obtain a Stream to the mutants List.
Stream<String> mutantStream = mutants.stream();

// Getting Spliterator object on mutantStream.
Spliterator<String> mutantList = mutantStream.spliterator();

To demonstrate some of these methods, let us run them separately:

// .estimateSize() method
System.out.println("Estimate size: " + mutantList.estimateSize());

// .getExactSizeIfKnown() method
System.out.println("\nExact size: " + mutantList.getExactSizeIfKnown());

System.out.println("\nContent of List:");
// .forEachRemaining() method
mutantList.forEachRemaining((n) -> System.out.println(n));

// Obtaining another Stream to the mutant List.
Spliterator<String> splitList1 = mutantStream.spliterator();

// .trySplit() method
Spliterator<String> splitList2 = splitList1.trySplit();

// If splitList1 could be split, use splitList2 first.
if (splitList2 != null) {
    System.out.println("\nOutput from splitList2:");
    splitList2.forEachRemaining((n) -> System.out.println(n));
}

// Now, use the splitList1
System.out.println("\nOutput from splitList1:");
splitList1.forEachRemaining((n) -> System.out.println(n));

We will get the output:

Estimate size: 6

Exact size: 6

Content of List: 
Professor X
Magneto
Storm
Jean Grey
Wolverine
Mystique

Output from splitList2: 
Professor X
Magneto
Storm

Output from splitList1: 
Jean Grey
Wolverine
Mystique

4. Iterable()

If for some reason, we want to create a custom Iteratorinterfaces, how should we do? You must first know that this picture:

file

To create a custom Iterator, we need to .hasNext(), .next()and .remove()do a custom implementation.

In the Iteratorinterface, there is a method, which returns an iterator set of elements, i.e. .iterator()a method, there is a method to perform a method of operation of each element in the iterator, i.e. .dorEach()methods.

For example, suppose we are Tony Stark, we need to write custom iterators to list each piece of Iron Man suits the current arsenal.

First, let's create a class suit to get and set data:

public class Suit {

    private String codename;
    private int mark;

    public Suit(String codename, int mark) {
        this.codename = codename;
        this.mark = mark;
    }

    public String getCodename() { return codename; }

    public int getMark() { return mark; }

    public void setCodename (String codename) {this.codename=codename;}

    public void setMark (int mark) {this.mark=mark;}

    public String toString() {
        return "mark: " + mark + ", codename: " + codename;
    }
}

Let's write custom Iterator:

// Our custom Iterator must implement the Iterable interface
public class Armoury implements Iterable<Suit> {
    
    // Notice that we are using our own class as a data type
    private List<Suit> list = null;

    public Armoury() {
        // Fill the List with data
        list = new LinkedList<Suit>();
        list.add(new Suit("HOTROD", 22));
        list.add(new Suit("SILVER CENTURION", 33));
        list.add(new Suit("SOUTHPAW", 34));
        list.add(new Suit("HULKBUSTER 2.0", 48));
    }
    
    public Iterator<Suit> iterator() {
        return new CustomIterator<Suit>(list);
    }

    // Here we are writing our custom Iterator
    // Notice the generic class E since we do not need to specify an exact class
    public class CustomIterator<E> implements Iterator<E> {
    
        // We need an index to know if we have reached the end of the collection
        int indexPosition = 0;
        
        // We will iterate through the collection as a List
        List<E> internalList;
        public CustomIterator(List<E> internalList) {
            this.internalList = internalList;
        }

        // Since java indexes elements from 0, we need to check against indexPosition +1
        // to see if we have reached the end of the collection
        public boolean hasNext() {
            if (internalList.size() >= indexPosition +1) {
                return true;
            }
            return false;
        }

        // This is our custom .next() method
        public E next() {
            E val = internalList.get(indexPosition);

            // If for example, we were to put here "indexPosition +=2" we would skip every 
            // second element in a collection. This is a simple example but we could
            // write very complex code here to filter precisely which elements are
            // returned. 
            // Something which would be much more tedious to do with a for or while loop
            indexPosition += 1;
            return val;
        }
        // In this example we do not need a .remove() method, but it can also be 
        // written if required
    }
}

The last class is the main method:

public class IronMan {

    public static void main(String[] args) {

        Armoury armoury = new Armoury();

        // Instead of manually writing .hasNext() and .next() methods to iterate through 
        // our collection we can simply use the advanced forloop
        for (Suit s : armoury) {
            System.out.println(s);
        }
    }
}

Output is as follows:

mark: 22, codename: HOTROD
mark: 33, codename: SILVER CENTURION
mark: 34, codename: SOUTHPAW
mark: 48, codename: HULKBUSTER 2.0

5. Summary

In this paper, we discuss in detail how to use iterators in Java, even wrote a custom iterator to explore Iterableall the new possibilities of the interface.

We also discuss how Java is parallelized Stream, the use of Spliteratorinterface through the collection of internal optimization.


August welfare struck on time, public concern number backstage Re: July 003 can receive a translation of highlights oh go on welfare Re: 001, 002, you can receive!



img

Guess you like

Origin www.cnblogs.com/liululee/p/11416038.html