検索
ホームページ类库下载java类库JAVAのfor-eachループと反復

JAVAのfor-eachループと反復

Oct 19, 2016 am 09:59 AM
for-eachjavaサイクル反復する

1. イテレーター Iterator

インターフェース: Iterator

public interface Iterator<E>{

 boolean hasNext();

 E next();

 void remove();
 }

Iterator インターフェース API を見ると、これがコレクションを反復するためのイテレーターであることがわかります。イテレーターを使用すると、呼び出し元は、明確に定義されたセマンティクスを使用して、反復中にイテレーターが指すコレクションから要素を削除できます。

特に注目に値するのは、この反復子の Remove() メソッドの使用です。反復子によって返された最後の要素 (オプションの操作) を、反復子が指すコレクションから削除します。このメソッドは、next の呼び出しごとに 1 回だけ呼び出すことができます。このメソッド (remove メソッド) の呼び出し以外の方法で反復中にイテレーターが指すコレクションが変更された場合、イテレーターの動作は未定義です。インターフェイス設計者は、Iterator インターフェイスを設計するときに、反復中にイテレーターが指すコレクションを変更するためにイテレーター以外の Remove() メソッドが呼び出された場合、不確実な結果が生じることを指摘しました。具体的な結果は、反復子の特定の実装によって異なります。このような不確実な結果が発生する可能性のある状況に対応して、ArrayList を学習しているときにそのうちの 1 つ、つまり反復子が ConcurrentModificationException 例外をスローすることに遭遇しました。特定の例外は次のコードに示されています。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ItaratorTest {

    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("Android");
        list.add("IOS");
        list.add("Windows Mobile");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String lang = iterator.next();
            list.remove(lang);//will throw ConcurrentModificationException
        }
    }

}

このコードは、実行中に ConcurrentModificationException 例外をスローします。これは、イテレータの実行中に要素を削除するためにイテレータの Remove() メソッドを使用せず、ArrayList の Remove() メソッドを使用するためです。イテレータが指すコレクションを変更します。これはイテレータの設計原則に違反するため、例外が発生します。
報告された例外は次のとおりです:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:17)

2. for-each ループと反復子 Iterator

Java5 以降、Java には for-each ループがあり、コレクションと配列をループするために使用できます。 Foreach ループを使用すると、従来の for ループでインデックスを維持したり、イテレータ / ListIterator (ArrayList のイテレータ実装) を使用するときに while ループで hasNext() メソッドを呼び出すことなく、コレクションを反復処理できます。 for-each ループにより、コレクションまたは配列を走査するプロセスが簡素化されます。ただし、foreach ループを使用する場合は注意すべき点が 2 つあります。

foreach ループを使用するオブジェクトは Iterable インターフェイスを実装する必要があります

次の例を参照してください:

import java.util.ArrayList;

public class ForeachTest1 {

    public static void main(String args[]) {
        CustomCollection<String> myCollection = new CustomCollection<String>();
        myCollection.add("Java");
        myCollection.add("Scala");
        myCollection.add("Groovy");

        // What does this code will do, print language, throw exception or
        // compile time error
        for (String language : myCollection) {
            System.out.println(language);
        }
    }

    private class CustomCollection<T> {
        private ArrayList<T> bucket;

        public CustomCollection() {
            bucket = new ArrayList();
        }

        public int size() {
            return bucket.size();
        }

        public boolean isEmpty() {
            return bucket.isEmpty();
        }

        public boolean contains(T o) {
            return bucket.contains(o);
        }

        public boolean add(T e) {
            return bucket.add(e);
        }

        public boolean remove(T o) {
            return bucket.remove(o);
        }

    }
}

これは、コード内の CustomCollection クラスが Iterable インターフェイスを実装していないためです。コンパイル中に報告される内容は次のとおりです:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Can only iterate over an array or an instance of java.lang.Iterable

    at Text.ForeachTest1.main(ForeachTest1.java:15)

実際、Eclipse は、このコードを記述した後、コンパイルでエラーを見つけるまで待つ必要はありません。配列またはインスタンスのみを反復処理できます。 java.lang.Iterable

上記の例から再度確認できることは、foreach ループは Iterable インターフェースを実装するオブジェクトにのみ適用されるということです。すべての組み込み Collection クラスは java.util.Collection インターフェイスを実装し、Iterable を継承しているため、上記の問題を解決するには、単に CustomCollection に Collection インターフェイスを実装させるか、AbstractCollection を継承させるかを選択できます。解決策は次のとおりです:

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;

public class ForeachTest {
    public static void main(String args[]) {
        CustomCollection<String> myCollection = new CustomCollection<String>();
        myCollection.add("Java");
        myCollection.add("Scala");
        myCollection.add("Groovy");
        for (String language : myCollection) {
            System.out.println(language);
        }
    }

    private static class CustomCollection<T> extends AbstractCollection<T> {
        private ArrayList<T> bucket;

        public CustomCollection() {
            bucket = new ArrayList();
        }

        public int size() {
            return bucket.size();
        }

        public boolean isEmpty() {
            return bucket.isEmpty();
        }

        public boolean contains(Object o) {
            return bucket.contains(o);
        }

        public boolean add(T e) {
            return bucket.add(e);
        }

        public boolean remove(Object o) {
            return bucket.remove(o);
        }

        @Override
        public Iterator<T> iterator() {
            // TODO Auto-generated method stub
            return bucket.iterator();
        }
    }
}

2. foreach ループの内部実装も Iterator に依存します

foreach ループが内部実装として Iterator を使用するという事実を確認するために、この記事の最初の例を引き続き使用します。検証用:

public class ItaratorTest {

    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("Android");
        list.add("IOS");
        list.add("Windows Mobile");

        // example1
        // Iterator<String> iterator = list.iterator();
        // while (iterator.hasNext()) {
        // String lang = iterator.next();
        // list.remove(lang);
        // }

        // example 2
        for (String language : list) {
            list.remove(language);
        }
    }

}

プログラムの実行時に報告される例外:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:22)

この例外は、コレクションを走査するために for-each ループ内で Iterator が使用されていること、および変更をチェックする Iterator.next() を呼び出していることを示しています (の要素)、ConcurrentModificationException をスローします。

概要:

コレクションを走査するときに、走査中にコレクションを変更したい場合は、Iterator/listIterator を使用して変更する必要があります。そうしないと、「未確定の結果」が発生する可能性があります。

foreach ループはイテレータを通じて実装され、foreach ループを使用するオブジェクトは Iterable インターフェイスを実装する必要があります


声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール