it-swarm-vi.tech

Vòng lặp Java 'cho mỗi' hoạt động như thế nào?

Xem xét:

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

Vòng lặp for tương đương sẽ trông như thế nào nếu không sử dụng cho mỗi cú pháp ?

1377
Jay R.
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

Lưu ý rằng nếu bạn cần sử dụng i.remove(); trong vòng lặp của mình hoặc truy cập vào trình lặp thực tế theo một cách nào đó, bạn không thể sử dụng thành ngữ for ( : ), vì trình lặp thực tế chỉ được suy ra.

Như được ghi nhận bởi Denis Bueno, mã này hoạt động cho bất kỳ đối tượng nào thực hiện giao diện Iterable .

Ngoài ra, nếu phía bên phải của thành ngữ for (:) là một đối tượng array chứ không phải là một đối tượng Iterable, thì mã nội bộ sử dụng bộ đếm chỉ mục int và thay vào đó kiểm tra lại array.length. Xem Đặc tả ngôn ngữ Java .

1090
nsayer

Cấu trúc cho mỗi cũng hợp lệ cho mảng. ví dụ.

String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };

for (String fruit : fruits) {
    // fruit is an element of the `fruits` array.
}

về cơ bản là tương đương với

for (int i = 0; i < fruits.length; i++) {
    String fruit = fruits[i];
    // fruit is an element of the `fruits` array.
}

Vì vậy, tóm tắt tổng thể:
[.__.] [nsayer] Sau đây là dạng dài hơn của những gì đang xảy ra:

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

Lưu ý rằng nếu bạn cần sử dụng i.remove (); trong vòng lặp của bạn hoặc truy cập vào trình lặp thực tế theo một cách nào đó, bạn không thể sử dụng thành ngữ for (:) vì Iterator thực tế chỉ được suy ra.

[Denis Bueno]

Nó được ngụ ý bởi câu trả lời của người dùng, nhưng đáng chú ý là cú pháp OP cho (..) sẽ hoạt động khi "someList" là bất cứ thứ gì thực hiện Java.lang.Iterable - nó không phải là một danh sách hoặc một bộ sưu tập nào đó Java.util. Ngay cả các loại của riêng bạn, do đó, có thể được sử dụng với cú pháp này.

464
Mikezx6r

Vòng lặp foreach , được thêm vào Java 5 (còn được gọi là "vòng lặp nâng cao"), tương đương với việc sử dụng Java.util.Iterator - đó là đường cú pháp cho cùng một thứ. Do đó, khi đọc từng phần tử, từng phần một và theo thứ tự, luôn luôn nên chọn foreach trên một trình vòng lặp, vì nó thuận tiện và ngắn gọn hơn.

cho mỗi

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

Lặp lại

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

Có những tình huống bạn phải sử dụng trực tiếp Iterator. Ví dụ: cố gắng xóa một phần tử trong khi sử dụng foreach có thể (sẽ?) Dẫn đến ConcurrentModificationException.

foreach so với for: Khác biệt cơ bản

Sự khác biệt thực tế duy nhất giữa forforeach là, trong trường hợp các đối tượng có thể lập chỉ mục, bạn không có quyền truy cập vào chỉ mục. Một ví dụ khi vòng lặp for cơ bản được yêu cầu:

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

Mặc dù bạn có thể tự tạo một chỉ mục int-biến riêng biệt với foreach,

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

không được khuyến khích, vì phạm vi biến không lý tưởng và vòng lặp for cơ bản chỉ đơn giản là định dạng chuẩn và dự kiến ​​cho trường hợp sử dụng này.

foreach so với for: Hiệu suất

Khi truy cập các bộ sưu tập, một foreachnhanh hơn đáng kể so với truy cập mảng của vòng lặp for cơ bản. Tuy nhiên, khi truy cập mảng - ít nhất là với mảng nguyên thủy và mảng bao bọc - việc truy cập qua các chỉ mục nhanh hơn đáng kể.

Định thời gian cho sự khác biệt giữa truy cập iterator và chỉ mục cho các mảng int nguyên thủy

Các chỉ mục là 23 - 40 phần trăm nhanh hơn các trình vòng lặp khi truy cập các mảng int hoặc Integer. Đây là đầu ra từ lớp thử nghiệm ở dưới cùng của bài đăng này, tính tổng các số trong một mảng nguyên thủy 100 phần tử (A là iterator, B là chỉ mục):

[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)

Tôi cũng đã chạy nó cho một mảng Integer và các chỉ mục vẫn là người chiến thắng rõ ràng, nhưng chỉ nhanh hơn từ 18 đến 25%.

Đối với các bộ sưu tập, các trình vòng lặp nhanh hơn các chỉ mục

Tuy nhiên, đối với List trong số Integers, các trình vòng lặp là người chiến thắng rõ ràng. Chỉ cần thay đổi mảng int trong lớp thử nghiệm thành:

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

Và thực hiện các thay đổi cần thiết cho chức năng kiểm tra (int[] thành List<Integer>, length thành size(), v.v.):

[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)

Trong một thử nghiệm, chúng gần như tương đương, nhưng với các bộ sưu tập, iterator thắng.

* Bài đăng này dựa trên hai câu trả lời tôi đã viết trên Stack Overflow:

Một số thông tin khác:Cái nào hiệu quả hơn, vòng lặp for-every hoặc iterator?

Lớp kiểm tra đầy đủ

Tôi đã tạo ra lớp so sánh-thời gian-thời gian cần làm này sau khi đọc câu hỏi này trên Stack Overflow:

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://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-Java&quot;&gt;https://stackoverflow.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

}
141
aliteralmind

Đây là một câu trả lời không thừa nhận kiến ​​thức về Trình vòng lặp Java. Nó ít chính xác hơn, nhưng nó hữu ích cho giáo dục.

Trong khi lập trình, chúng ta thường viết mã trông như sau:

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

Cú pháp foreach cho phép mô hình chung này được viết theo cách tự nhiên hơn và ít gây ồn hơn về mặt cú pháp.

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

Ngoài ra, cú pháp này hợp lệ cho các đối tượng như Danh sách hoặc Bộ không hỗ trợ lập chỉ mục mảng, nhưng thực hiện giao diện Iterable Java.

125
MRocklin

Vòng lặp for-every trong Java sử dụng cơ chế lặp bên dưới. Vì vậy, nó giống hệt như sau:

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

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

Trong các tính năng của Java 8, bạn có thể sử dụng tính năng này:

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

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

Đầu ra

First
Second
Third
23
Jrovalle

Nó được ngụ ý bởi câu trả lời của người dùng, nhưng đáng chú ý là cú pháp của OP cho (..) sẽ hoạt động khi "someList" là bất cứ điều gì thực hiện Java.lang.Iterable - nó không phải là một danh sách, hoặc một số bộ sưu tập từ Java.util. Ngay cả các loại của riêng bạn, do đó, có thể được sử dụng với cú pháp này.

22
EfForEffort

Cú pháp vòng lặp foreach là:

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

Thí dụ:

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

Đầu ra:

Java
Coffe
Is
Cool

CẢNH BÁO: Bạn có thể truy cập các phần tử mảng bằng vòng lặp foreach, nhưng bạn KHÔNG thể khởi tạo chúng. Sử dụng vòng lặp for ban đầu cho điều đó.

CẢNH BÁO: Bạn phải khớp loại của mảng với đối tượng khác.

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

Nếu bạn muốn chỉnh sửa các thành phần, hãy sử dụng vòng lặp for ban đầu như thế này:

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

Bây giờ nếu chúng ta đổ s vào bàn điều khiển, chúng ta sẽ nhận được:

hello
2 is cool
hello
hello
21
PrivateName

Cấu trúc vòng lặp "for-every" của Java sẽ cho phép lặp qua hai loại đối tượng:

  • T[] (mảng thuộc bất kỳ loại nào)
  • Java.lang.Iterable<T>

Giao diện Iterable<T> chỉ có một phương thức: Iterator<T> iterator(). Điều này hoạt động trên các đối tượng loại Collection<T> vì giao diện Collection<T> mở rộng Iterable<T>.

20
Ryan Delucchi

Như được định nghĩa trong JLS cho mỗi vòng lặp có thể có hai dạng:

  1. Nếu loại Biểu thức là một kiểu con của Iterable thì bản dịch là:

    List<String> someList = new ArrayList<String>();
    someList.add("Apple");
    someList.add("Ball");
    for (String item : someList) {
        System.out.println(item);
    }
    
    // IS TRANSLATED TO:
    
    for(Iterator<String> stringIterator = someList.iterator(); stringIterator.hasNext(); ) {
        String item = stringIterator.next();
        System.out.println(item);
    }
    
  2. Nếu Biểu thức nhất thiết phải có kiểu mảng T[] thì:

    String[] someArray = new String[2];
    someArray[0] = "Apple";
    someArray[1] = "Ball";
    
    for(String item2 : someArray) {
        System.out.println(item2);
    }
    
    // IS TRANSLATED TO:
    for (int i = 0; i < someArray.length; i++) {
        String item2 = someArray[i];
        System.out.println(item2);
    }
    

Java 8 đã giới thiệu các luồng hoạt động thường tốt hơn. Chúng ta có thể sử dụng chúng như:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
20
i_am_zero

Khái niệm về vòng lặp foreach như được đề cập trong Wikipedia được nêu rõ dưới đây:

Tuy nhiên, không giống như các cấu trúc vòng lặp khác, các vòng lặp foreach thường duy trì không có bộ đếm rõ ràng : về cơ bản chúng nói "làm điều này với mọi thứ trong tập hợp này", thay vì "làm điều này x lần". Điều này tránh các lỗi tiềm ẩn từng lỗi một và làm cho mã dễ đọc hơn.

Vì vậy, khái niệm về vòng lặp foreach mô tả rằng vòng lặp không sử dụng bất kỳ bộ đếm rõ ràng nào, điều đó có nghĩa là không cần sử dụng các chỉ mục để duyệt qua danh sách, do đó nó giúp người dùng không bị lỗi. Để mô tả khái niệm chung về lỗi này, chúng ta hãy lấy một ví dụ về vòng lặp để duyệt qua danh sách bằng các chỉ mục.

// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){

}

Nhưng giả sử nếu danh sách bắt đầu với chỉ số 1 thì vòng lặp này sẽ đưa ra một ngoại lệ vì nó sẽ không tìm thấy phần tử nào ở chỉ số 0 và lỗi này được gọi là lỗi do lỗi. Vì vậy, để tránh lỗi này, một khái niệm về vòng lặp foreach được sử dụng. Có thể có những lợi thế khác nữa, nhưng đây là những gì tôi nghĩ là khái niệm chính và lợi thế của việc sử dụng vòng lặp foreach.

15
oneConsciousness

Cũng lưu ý rằng việc sử dụng phương pháp "foreach" trong câu hỏi ban đầu có một số hạn chế, chẳng hạn như không thể xóa các mục khỏi danh sách trong quá trình lặp.

Vòng lặp for mới dễ đọc hơn và loại bỏ sự cần thiết của một trình vòng lặp riêng biệt, nhưng chỉ thực sự có thể sử dụng được trong các lần lặp chỉ đọc.

9
billjamesdev

Sử dụng các phiên bản Java cũ hơn bao gồm Java 7, bạn có thể sử dụng vòng lặp foreach như sau.

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

Sau đây là cách sử dụng vòng lặp foreach mới nhất trong Java 8

(lặp một Danh sách với forEach + biểu thức lambda hoặc tham chiếu phương thức)

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

Để biết thêm thông tin tham khảo liên kết này.

https://www.mkyong.com/Java8/Java-8-foreach-examples/

9
Dulith De Costa

Đây là một biểu thức tương đương.

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
9
Hank

Một thay thế cho forEach để tránh "cho mỗi" của bạn:

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

Biến thể 1 (đồng bằng):

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

Biến 2 (thực thi song song (nhanh hơn)):

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

Nó thêm vẻ đẹp cho mã của bạn bằng cách loại bỏ tất cả các lộn xộn vòng lặp cơ bản. Nó cung cấp một cái nhìn rõ ràng cho mã của bạn, được chứng minh dưới đây.

Vòng lặp for bình thường:

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

Sử dụng cho mỗi:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-Each là một cấu trúc trên một bộ sưu tập thực hiện Iterator . Hãy nhớ rằng, bộ sưu tập của bạn nên thực hiện Iterator ; nếu không, bạn không thể sử dụng nó cho mỗi.

Dòng sau được đọc là " cho mỗi t TimerTask trong danh sách. "

for (TimerTask t : list)

Có ít cơ hội hơn cho các lỗi trong trường hợp cho mỗi. Bạn không phải lo lắng về việc khởi tạo trình vòng lặp hoặc khởi tạo bộ đếm vòng lặp và chấm dứt nó (nơi có phạm vi cho các lỗi).

7
Manohar

Nó sẽ trông giống như thế này. Rất giòn.

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

Có một cách viết tốt về cho mỗi trong tài liệu Sun .

6
Pete

Trước Java 8, bạn cần sử dụng như sau:

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

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

Tuy nhiên, với việc giới thiệu Luồng trong Java 8, bạn có thể thực hiện điều tương tự với cú pháp ít hơn nhiều. Ví dụ: đối với someList của bạn, bạn có thể làm:

someList.stream().forEach(System.out::println);

Bạn có thể tìm thêm về luồng tại đây .

6
stackFan

Như rất nhiều câu trả lời hay đã nói, một đối tượng phải thực hiện Iterable interface nếu nó muốn sử dụng vòng lặp for-each.

Tôi sẽ đăng một ví dụ đơn giản và cố gắng giải thích theo cách khác cách vòng lặp for-each hoạt động.

Ví dụ về vòng lặp 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);
        }
    }
}

Sau đó, nếu chúng ta sử dụng javap để dịch ngược lớp này, chúng ta sẽ lấy mẫu mã byte này:

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;

Như chúng ta có thể thấy từ dòng cuối cùng của mẫu, trình biên dịch sẽ tự động chuyển đổi việc sử dụng từ khóa for-each sang sử dụng Iterator tại thời điểm biên dịch. Điều đó có thể giải thích tại sao đối tượng, không triển khai Iterable interface, sẽ ném Exception khi nó cố gắng sử dụng vòng lặp for-each.

5
L Joey

Trong Java 8, họ đã giới thiệu forEach. Sử dụng nó Danh sách, Bản đồ có thể được lặp.

Lặp lại một Danh sách bằng cách sử dụng cho mỗi

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

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

hoặc là

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

Lặp lại Bản đồ bằng cách sử dụng cho mỗi

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

hoặc là

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});
5
vivekkurien
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}
3
Santhosh Rajkumar

Java cho mỗi vòng lặp (còn được nâng cao cho vòng lặp) là phiên bản đơn giản hóa của vòng lặp for. Ưu điểm là có ít mã để viết và ít biến hơn để quản lý. Nhược điểm là bạn không có quyền kiểm soát giá trị bước và không có quyền truy cập vào chỉ mục vòng lặp bên trong thân vòng lặp.

Chúng được sử dụng tốt nhất khi giá trị bước là số gia đơn giản là 1 và khi bạn chỉ cần truy cập vào phần tử vòng lặp hiện tại. Ví dụ: nếu bạn cần lặp qua mọi phần tử trong một mảng hoặc Bộ sưu tập mà không nhìn trộm phía trước hoặc phía sau phần tử hiện tại.

Không có khởi tạo vòng lặp, không có điều kiện boolean và giá trị bước là ẩn và là một bước tăng đơn giản. Đây là lý do tại sao chúng được coi là đơn giản hơn nhiều so với thông thường cho các vòng lặp.

Tăng cường cho các vòng lặp theo thứ tự thực hiện này:

1) thân vòng

2) lặp lại từ bước 1 cho đến khi toàn bộ mảng hoặc bộ sưu tập đã được duyệt qua

Ví dụ - Mảng số nguyên

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

Biến currentValue giữ giá trị hiện tại được lặp trong mảng intArray. Lưu ý rằng, không có giá trị bước rõ ràng - nó luôn luôn tăng 1.

Các dấu hai chấm có thể được nghĩ đến có nghĩa là trên thế giới. Vì vậy, trạng thái khai báo vòng lặp nâng cao: lặp qua intArray và lưu trữ mảng int value in biến currentValue hiện tại.

Đầu ra:

1
3
5
7
9

Ví dụ - Mảng chuỗi

Chúng ta có thể sử dụng vòng lặp for-Each để lặp qua một chuỗi các chuỗi. Khai báo vòng lặp trạng thái: lặp qua mảng Chuỗi myStrings và lưu trữ giá trị Chuỗi hiện tại in biến currentString.

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

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

Đầu ra:

alpha
beta
gamma
delta

Ví dụ - Danh sách

Vòng lặp for được tăng cường cũng có thể được sử dụng để lặp qua Java.util.List như sau:

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

Khai báo vòng lặp trạng thái: loop over myList List of String và lưu trữ giá trị List hiện tại in biến currentItem.

Đầu ra:

alpha
beta
gamma
delta

Ví dụ - Đặt

Vòng lặp for được tăng cường cũng có thể được sử dụng để lặp qua Java.util.Set như sau:

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

Khai báo vòng lặp trạng thái: loop over my Set Set of String và lưu trữ giá trị Set hiện tại in biến currentItem. Lưu ý rằng vì đây là Tập hợp, các giá trị Chuỗi trùng lặp không được lưu trữ.

Đầu ra:

alpha
delta
beta
gamma

Nguồn: Vòng lặp trong Java - Hướng dẫn cơ bản

3
gomisha

Thành ngữ Java cho mỗi thành ngữ chỉ có thể được áp dụng cho các mảng hoặc đối tượng kiểu * Iterable . Thành ngữ này là ẩn vì nó thực sự được hỗ trợ bởi Iterator. Iterator được lập trình viên lập trình và thường sử dụng một chỉ số nguyên hoặc một nút (tùy thuộc vào cấu trúc dữ liệu) để theo dõi vị trí của nó. Trên giấy, nó chậm hơn một vòng lặp for thông thường, ít nhất là đối với các cấu trúc "tuyến tính" như mảng và Danh sách nhưng nó cung cấp sự trừu tượng hóa lớn hơn.

2
WIll

Điều này có vẻ điên rồ nhưng hey nó hoạt động

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

Những công việc này. Phép thuật

1
Rei Brown