順序 - list ループ java




Java for eachループはどのように機能しますか? (18)

検討してください:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

同等のforループは、各構文に対してforを使用しないとどのように見えますか?


Java 8では、forEachを導入しました。 リストを使用すると、地図をループすることができます。

それぞれのためにリストをループする

List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");

someList.forEach(listItem -> System.out.println(listItem))

または

someList.forEach(listItem-> {
     System.out.println(listItem); 
});

それぞれを使用してマップをループする

Map<String, String> mapList = new HashMap<>();
    mapList.put("Key1", "Value1");
    mapList.put("Key2", "Value2");
    mapList.put("Key3", "Value3");

mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));

または

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});

Java 8の機能では、これを使用することができます:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

出力

First
Second
Third

Javaの "for-each"ループ構造では、2つのタイプのオブジェクトに対する反復が可能です:

  • T[] (任意の型の配列)
  • java.lang.Iterable<T>

Iterable<T>インターフェースには1つのメソッドしかありません: Iterator<T> iterator()Collection<T>インタフェースがIterable<T>拡張しているため、これはCollection<T>型のオブジェクトで機能します。


Javaのfor-eachループは、基本的なイテレーター・メカニズムを使用します。 したがって、以下と同じです。

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}

foreachループの構文は次のとおりです。

for (type obj:array) {...}

例:

String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
    System.out.println(str);
}

出力:

Java
Coffe
Is
Cool

警告:foreachループを使用して配列要素にアクセスできますが、初期化することはできません。 そのforループを使用します。

警告:配列の型と他のオブジェクトを一致させる必要があります。

for (double b:s) // Invalid-double is not String

要素を編集する場合は、次のように元のforループを使用forます。

for (int i = 0; i < s.length-1 /*-1 because of the 0 index */; i++) {
    if (i==1) //1 because once again I say the 0 index
        s[i]="2 is cool";
    else
        s[i] = "hello";
}

コンソールにsをダンプすると、次のようになります。

hello
2 is cool
hello
hello

Java 5で追加されたdocs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html ( "for for enhanced loop"とも呼ばれます)は、 java.util.Iteratorを使用することと同じです。 したがって、各要素を1つずつ順番に読むときには、より便利で簡潔なので、常にイテレータを使用してforeachを選択する必要があります。

foreach

for(int i : intList) {
   System.out.println("An element in the list: " + i);
}

イテレータ

Iterator<Integer> intItr = intList.iterator();
while(intItr.hasNext()) {
   System.out.println("An element in the list: " + intItr.next());
}

Iterator直接使用する必要がある状況があります。 たとえば、 foreachを使用している間に要素を削除しようとすると、 ConcurrentModificationExceptionます。

foreachfor :基本的な違い

forforeachの唯一の実際的な違いは、索引付け可能オブジェクトの場合、索引へのアクセス権がないことです。 基本forループが必要な場合の例

for(int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

foreach int-variableという別のインデックスを手動で作成することもできますが、

int idx = -1;
for(int i : intArray) {
   idx++;
   ...
}

variable-scopeが理想的ではないため、推奨されません。また、 forループの基本は、このユースケースの標準および期待される形式です。

foreachfor :パフォーマンス

コレクションにアクセスするとき、 foreachは基本的なforループの配列アクセスよりはるかに高速です。 ただし、配列にアクセスするときは、少なくともプリミティブ配列とラッパー配列を使用すると、索引によるアクセスが劇的に高速になります。

プリミティブint配列のイテレータとインデックスのアクセスの違いをタイミングする

int配列またはInteger配列にアクセスする場合、インデックスはイテレータより23〜40%高速です。 この記事の一番下にあるテストクラスの出力は、100要素のプリミティブ型の配列(Aはイテレータ、Bはインデックス)の数値を合計したものです。

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)

私はIntegerアレイでもこれを実行しましたが、インデックスはまだ明らかに勝っていますが、わずか18〜25%しか高速化していません。

コレクションの場合、イテレータはインデックスより高速です

ただし、 List of Integers場合、イテレータは明確な勝者です。 テストクラスのint配列を次のように変更してください:

List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});

そして、テスト関数( int[] to List<Integer>length to size()など)に必要な変更を加えます:

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)

あるテストではほぼ同等ですが、コレクションではイテレータが勝ちます。

*この投稿は、で書いた2つの回答に基づいています。

さらに詳しい情報: どちらが効率的か、for-eachループか、イテレータか

完全なテストクラス

この質問を読んだら、 この 2つのことを比較する時代のこのクラスを作成しました:

import  java.text.NumberFormat;
import  java.util.Locale;

/**
   &lt;P&gt;{@code java TimeIteratorVsIndexIntArray 1000000}&lt;/P&gt;

   @see  &lt;CODE&gt;&lt;A HREF=&quot;https://.com/questions/180158/how-do-i-time-a-methods-execution-in-java&quot;&gt;https://.com/questions/180158/how-do-i-time-a-methods-execution-in-java&lt;/A&gt;&lt;/CODE&gt;
 **/
public class TimeIteratorVsIndexIntArray {

    public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);

    public static final void main(String[] tryCount_inParamIdx0) {
        int testCount;

        // Get try-count from a command-line parameter
        try {
           testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
        }
        catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
           throw  new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
        }

        //Test proper...START
        int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

        long lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testIterator(intArray);
        }

        long lADuration = outputGetNanoDuration("A", lStart);

        lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testFor(intArray);
        }

        long lBDuration = outputGetNanoDuration("B", lStart);

        outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
    }

    private static final void testIterator(int[] int_array) {
       int total = 0;
       for(int i = 0; i < int_array.length; i++) {
          total += int_array[i];
       }
    }

    private static final void testFor(int[] int_array) {
       int total = 0;
       for(int i : int_array) {
          total += i;
       }
    }
    //Test proper...END

    //Timer testing utilities...START
    public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
        long lDuration = System.nanoTime() - l_nanoStart;
        System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
        return  lDuration;
    }

    public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
        long lDiff = -1;
        double dPct = -1.0;
        String sFaster = null;
        if(l_aDuration > l_bDuration) {
            lDiff = l_aDuration - l_bDuration;
            dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
            sFaster = "B";
        }
        else {
            lDiff = l_bDuration - l_aDuration;
            dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
            sFaster = "A";
        }
        System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
        return  lDiff;
   }

   //Timer testing utilities...END

}

各ループJava (aka enhanced forループ)は、forループの簡略版です。 利点は、書き込むコードが少なく、管理する変数が少ないことです。 欠点は、ステップ値を制御することができず、ループ本体内のループ索引にアクセスできないことです。

ステップ値が1の単純増分で、現在のループ要素にアクセスする必要がある場合に最適です。 たとえば、配列またはコレクション内のすべての要素を、現在の要素の前後に覗き込むことなくループする必要がある場合です。

ループの初期化もブール条件もなく、ステップ値は暗黙的で、単純な増分です。 これが、通常のforループよりもはるかに簡単だと考えられる理由です。

拡張forループは、次の実行順序に従います。

1)ループ本体

2)配列全体またはコレクションがトラバースされるまで、ステップ1から繰り返す

例 - 整数配列

int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
  System.out.println(currentValue);
}

currentValue変数は、intArray配列でループされている現在の値を保持します。 明示的なステップ値はないことに注意してください。常に1ずつ増加します。

結腸は「in」を意味すると考えることができる。 したがって、拡張されたforループ宣言では、intArrayをループし、現在の配列のint値 currentValue変数に格納します。

出力:

1
3
5
7
9

例 - 文字列配列

for-eachループを使用して、文字列の配列を反復処理できます。 ループ宣言は:myStrings String配列をループし、現在のString値 currentString変数に格納します。

String [] myStrings  = {
  "alpha",
  "beta",
  "gamma",
  "delta"
};

for(String currentString : myStrings) {
  System.out.println(currentString);
}

出力:

alpha
beta
gamma
delta

例 - リスト

拡張されたforループは、次のようにjava.util.Listを反復処理するためにも使用できます。

List<String> myList = new ArrayList<String>();
myList.add("alpha");
myList.add("beta");
myList.add("gamma");
myList.add("delta");

for(String currentItem : myList) {
  System.out.println(currentItem);
}

ループ宣言では、次のように記述されています。myList List of Stringsのリストで、現在のList値 currentItem変数に格納します。

出力:

alpha
beta
gamma
delta

例 - 設定

拡張されたforループは、次のようにjava.util.Setを反復処理するためにも使用できます。

Set<String> mySet = new HashSet<String>();
mySet.add("alpha");
mySet.add("alpha");
mySet.add("beta");
mySet.add("gamma");
mySet.add("gamma");
mySet.add("delta");

for(String currentItem : mySet) {
  System.out.println(currentItem);
}

ループ宣言は次のように述べています。mySet Set of Stringsをループし、現在のSet値 currentItem変数に格納します。 これはSetなので、重複するString値は格納されません。

出力:

alpha
delta
beta
gamma

ソース: Javaのループ - アルティメットガイド


Java 7を含む古いJavaバージョンを使用すると、 foreachループを次のように使用できます。

List<String> items = new ArrayList<>();
        items.add("A");
        items.add("B");
        items.add("C");
        items.add("D");
        items.add("E");

        for(String item : items){
            System.out.println(item);
        }

以下は、 Java 8 foreachループを使用する最新の方法です

forEach +ラムダ式またはメソッド参照でループリストを作成する)

//lambda
    //Output : A,B,C,D,E
    items.forEach(item->System.out.println(item));


//method reference
    //Output : A,B,C,D,E
    items.forEach(System.out::println);

詳細については、このリンクを参照してください。

https://www.mkyong.com/java8/java-8-foreach-examples/


あなたの「for each」を避けるためにforEachに代わる方法:

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

バリアント1(プレーン):

someList.stream().forEach(listItem -> {
    System.out.println(listItem);
});

バリアント2(並列実行(高速)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});

ここでは、Javaイテレータの知識がない答えです。 それはそれほど正確ではありませんが、教育に役立ちます。

プログラミング時には、次のようなコードを書くことがよくあります:

char[] grades = ....
for(int i = 0; i < grades.length; i++) {   // for i goes from 0 to grades.length
    System.out.print(grades[i]);           // Print grades[i]
}

foreach構文では、この共通のパターンをより自然で文法的に騒々しい方法で書くことができます。

for(char grade : grades) {   // foreach grade in grades
    System.out.print(grade); // print that grade
}

さらに、この構文は、配列索引付けをサポートしていないが、Java Iterableインターフェースを実装しているリストやセットなどのオブジェクトに有効です。


これはnsayerの答えによって示唆されていますが、OPのfor(..)構文は、 "someList"がjava.lang.Iterableを実装するものであれば動作することに注意する価値があります。リストでなくても、コレクションである必要はありませんjava.util。 したがって、独自の型であっても、この構文で使用できます。


これは狂っているようだがねえ

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

これは機能します。 魔法


それはこのようなものに見えるでしょう。 非常に無謀です。

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

Sunのマニュアルには、 それぞれに優れた記述があります


また、元の質問で "foreach"メソッドを使用すると、反復中にリストからアイテムを削除できないなど、いくつかの制限があります。

新しいforループは読みやすく、別のイテレータの必要性を排除しますが、読み取り専用の繰り返しパスでは本当に使用できます。


多くの良い答えが述べるように、 for-eachループを使用する場合、オブジェクトはIterable interface実装する必要があります。

私は簡単な例を投稿し、 for-eachループがどのように動作するかを別の方法で説明しようとします。

for-eachループの例:

public class ForEachTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("111");
        list.add("222");

        for (String str : list) {
            System.out.println(str);
        }
    }
}

次に、 javapを使ってこのクラスを逆コンパイルすると、このバイトコードサンプルが取得されます:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

サンプルの最後の行からわかるように、コンパイラはfor-eachキーワードの使用をコンパイル時に自動的にIteratorの使用に変換します。 これは、 Iterable interface実装していないオブジェクトがfor-eachループを使用しようとすると、 Exceptionをスローする理由を説明します。


List<Item> Items = obj.getItems();
for(Item item:Items)
             {
                System.out.println(item); 
             }

Itemsテーブル内のすべてのオブジェクトを反復処理します。


for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}

public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}




syntactic-sugar