Javaの反復インタフェース:イテレータ、反復子とSpliterator

1.はじめに

私たちが使用している場合forwhile、コレクションの要素を反復処理するループを、Iteratorそれは私たちも私たちだけではなく、コレクションを通じて、それを変更することができますが、また聞かせて、インデックス位置を心配しないですることができます。あなたは要素のサイクルを削除したい場合たとえば、for周期は必ずしも常に可能ではありません。

カスタムイテレータと組み合わせることで、我々としても、前方と後方、より複雑なオブジェクトを反復処理し、非常に明確になるだろうその利点を活用する方法を知ることができます。

この記事では、どのように使用する深さに説明しますIteratorIterableインタフェース。

2.イテレータ()

Iteratorインタフェースは、反復要素を設定するために使用されているListSet又はMap)。要素を一つずつ取得するために使用され、各構成要素に必要なときに動作を行います。

以下の方法が実行されるオペレーションのセットを横断するために使用されます。

  • .hasNext():あなたは達していない場合は、コレクションの末尾が返されるtrueそれ以外の場合は、false
  • .next():コレクション内の次の要素を返します
  • .remove():最後の要素が返されたコレクションの反復子から削除されます
  • .forEachRemaining():指定された操作を実行するために、残りの要素のそれぞれに設定されています

まず、コレクションのイテレータので、のは簡単にはいくつかの要素が含まれてやらせます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");

私たちは、このコレクションを反復処理するために、単純なループを使用することができます。

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

しかし、私たちは、イテレータを探検したいと思います:

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

私たちはこれが欲しい場合はArrayList要素を削除するには、何が起こるでしょうか?のは、定期的に使用してみましょうforサイクル:

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

我々は厄介を受け取ることになりますIndexOutOfBoundsException

Simple loop example:

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

この変更は、コレクションの繰り返し処理を行う場合、その大きさに重要である、強化forあまりにも、循環を:

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

もう一度、我々は別の例外を受け取りました。

Simple loop example:

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

その後、イテレータは計画通りにトラバース続けることを保証しながら、それは、コレクションから要素を削除し、仲介として機能し、便利になります:

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

これは、コレクションを横断しながら、要素を削除する安全な方法を確保することです。

そして、要素が削除されているかどうかを確認します。

// 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);

次のように出力されます。

For Each Remaining Example:

Black Widow
Captain America
Doctor Strange

あなたが見ることができるように、人々はよりアリ持って复仇者联盟削除されたのリストを。

2.1。反復子()

ListIterator継承されますIteratorインターフェイス。のみでのList使用に行って、あなたが戻って前に戻ったりするために正面から繰り返すことができることを意味、双方向反復することができます。カーソルが常に置かれているので、それはまた、現在の要素ないList二つの要素の間、私たちが使う.previous().next()の要素にアクセスします。

Iteratorそして、ListIteratorの違いは何ですか?

まず第一に、Iteratorそれがために使用することができるの任意のセット - 、ListMap などが挙げられます。QueueSet

ListIterator唯一、この制限を追加することで、リストを適用することができListIterator、より特異的であることができる方法の面で、そのため、私たちは横断しながら、彼らはそれを修正するために私たちを助けることができる多くの新しい方法を導入しました。

あなたが作業している場合はList(達成するためにArrayListLinkedListなど)、そして使用ListIteratorがより望ましい数を。

ここでは、使用する可能性があります方法は次のとおりです。

  • .add(E e):リストに要素を追加します。
  • .remove():リストから削除する.next()か、.previous()最後の要素が返されます。
  • .set(E e):リストをカバーするために、指定された要素を使用して、.next()または.previous()最後の要素を返します。
  • .hasNext():あなたがリストの終わりに達していない場合は返しtrueそうfalse
  • .next():次の要素のリストを返します。
  • .nextIndex():次の要素のインデックスを返します。
  • .hasPrevious():あなたはまだリストの先頭に達していない場合は、返されtrueそうfalse
  • .previous():リストの前の要素を返します。
  • .previousIndex():要素のインデックスを返します。

ここでも、の構成要素をいくつか使ってみましょうArrayList

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

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

私たちが使用してみましょうListIteratorリストを横断し、その要素を印刷するには:

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

もちろん、それが動作しますIterator同じ。次のように出力されます。

Original contents of our List: 

Daredevil
Luke Cage
Jessica Jones
Iron Fist

それでは、いくつかの要素を変更してみましょう:

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

印刷一覧今、その後、次のような結果が得られます。

Modified contents of our List:

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

今、私たちができるのと同じように、のは、逆方向リストを手放すListIteratorことを実行します。

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

次のように出力されます。

Modified List backwards:

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

3. Spliterator()

Spliteratorインタフェースは、機能的であるIterator同じ。あなたは直接使用する必要はないかもしれませんSpliteratorが、のは、いくつかのユースケースに移りましょう。

しかし、あなたが精通している必要がありJavaストリームJavaでラムダ式

我々が一覧表示されますが、Spliteratorすべてのメソッドがありますが、Spliteratorすべての作業インターフェイスは、この記事の範囲外です。例を通して、私たちが議論するSpliterator私たちが分解することができる、より効率的な並列化トラバースを使用する方法Stream

私たちは、対処Spliterator方法をするときに使用されます。

  • .characteristics()

    :Spliteratorに戻ったとして、

    int

    固有値。これらは、次のとおりです。

    • ORDERED
    • DISTINCT
    • SORTED
    • SIZED
    • CONCURRENT
    • IMMUTABLE
    • NONNULL
    • SUBSIZED
  • .estimateSize():としてトラバースに戻るlong返される返すことができない場合は、遭遇した要素数の値の推定値long.MAX_VALUE

  • .forEachRemaining(E e):指定された操作を実行するために残りの要素の各々を設定するために。

  • .getComparator():場合はSpliterator、ソースが作られComparator、それがソートされた返されますComparator

  • .getExactSizeIfKnown():サイズが知られている場合は、返し.estimateSize()そう-1

  • .hasCharacteristics(int characteristics):これが場合Spliteratorされ.characteristics()、すべての与えられた特性を含む返されますtrue

  • .tryAdvance(E e):残りの要素が存在する場合、その戻り値で指定された操作を実行しtrue、さもなければ、false

  • .trySplit():これは場合はSpliterator分割することができ、それが返されますSpliterator。このメソッドから戻って、これがされないとき、カバー要素をSpliteratorカバーしました。

いつものように、のは簡単な始めましょうArrayListスタート:

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");

今、私たちはする必要がSpliterator適用されますStream幸い、コレクションフレームワークのために、それは簡単であるArrayListStreamの間で変換します。

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

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

これらの方法のうちのいくつかを実証するために、私たちはそれらを個別に実行してみましょう:

// .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));

私たちは、出力が得られます。

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.反復処理可能()

何らかの理由で、私たちは、カスタム作成する場合Iteratorのインターフェイスを、私たちはどのようにすればよいですか?あなたは最初に、この絵を知っている必要があります。

ファイル

カスタムを作成するためにIterator、私たちのようにする必要があり.hasNext().next()および.remove()カスタム実装を行います。

Iteratorインターフェース要素のイテレータセット、即ち返すメソッド、ある.iterator()方法、すなわちイテレータの各要素の動作の方法を実行するための方法であって、ある.dorEach()方法。

例えば、我々はトニー・スタークあるとし、我々は、アイアンマン、現在の武器庫に合っの各部分をリストするカスタムイテレータを記述する必要があります。

まずは、データを取得および設定するために、クラスのスーツを作成してみましょう:

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

のは、カスタム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
    }
}

最後のクラスは、mainメソッドです。

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

次のように出力されます。

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

5.まとめ

本論文では、私たちも、探求するカスタムイテレータを書いて、Javaでイテレータを使用する方法を詳細に議論するIterableインタフェースのすべての新たな可能性を。

我々はまた、Javaがストリームの使用並列化する方法を話し合うSpliterator内部の最適化のコレクションをインタフェースを。


8月の福祉は時間に打たれ、国民の関心番号舞台裏日時:7月003は、オハイオ州のハイライトの翻訳受け取ることができる福祉の日時に行く:001、002、あなたが受け取ることができます!



IMG

おすすめ

転載: www.cnblogs.com/liululee/p/11416038.html