杰瑞科技汇

Java for each与for循环该怎么选?

Of course! The for-each loop, also known as the enhanced for loop, is a core feature in Java for iterating over collections and arrays. It's a more concise and readable way to loop than the traditional for loop when you just need to access every element.

Java for each与for循环该怎么选?-图1
(图片来源网络,侵删)

Here's a complete guide, from basic syntax to advanced examples and best practices.


Basic Syntax

The syntax is simple and declarative: you declare a variable that will hold each element from the collection, and the loop automatically iterates through the entire collection.

for (Type variable : collection) {
    // Code to execute for each element
}
  • Type: The data type of the elements in the collection (e.g., String, Integer, Object).
  • variable: A new variable that will hold the current element in each iteration. Its type must be compatible with the collection's element type.
  • collection: The array or Iterable object (like List, Set, etc.) you want to loop over.

How It Works: The Magic Behind the Scenes

The for-each loop is essentially syntactic sugar. The Java compiler automatically converts it into a standard for loop using an Iterator.

Your code:

Java for each与for循环该怎么选?-图2
(图片来源网络,侵删)
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

What the compiler sees (roughly):

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Get an iterator from the list
Iterator<String> iterator = names.iterator();
// Loop as long as there are more elements
while (iterator.hasNext()) {
    // Get the next element and assign it to the variable
    String name = iterator.next();
    System.out.println(name);
}

This is why the for-each loop can only be used with objects that implement the java.lang.Iterable interface (which includes all collection classes like List, Set, etc.) or with arrays.


Examples with Different Data Types

a) Iterating over an Array

public class ArrayExample {
    public static void main(String[] args) {
        String[] fruits = { "Apple", "Banana", "Cherry" };
        System.out.println("Fruits:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        // With primitive types
        int[] numbers = { 10, 20, 30, 40, 50 };
        System.out.println("\nNumbers:");
        for (int number : numbers) {
            System.out.println(number);
        }
    }
}

Output:

Fruits:
Apple
Banana
Cherry
Numbers:
10
20
30
40
50

b) Iterating over a List

This is the most common use case.

Java for each与for循环该怎么选?-图3
(图片来源网络,侵删)
import java.util.Arrays;
import java.util.List;
public class ListExample {
    public static void main(String[] args) {
        // Create a List
        List<Integer> scores = Arrays.asList(95, 88, 76, 100, 54);
        System.out.println("Student Scores:");
        for (Integer score : scores) {
            System.out.println("Score: " + score);
        }
    }
}

Output:

Student Scores:
Score: 95
Score: 88
Score: 76
Score: 100
Score: 54

c) Iterating over a Set

Since a Set guarantees uniqueness, the for-each loop is perfect for processing unique items. The order of iteration is not guaranteed (unless it's a LinkedHashSet or TreeSet).

import java.util.HashSet;
import java.util.Set;
public class SetExample {
    public static void main(String[] args) {
        Set<String> uniqueTags = new HashSet<>();
        uniqueTags.add("java");
        uniqueTags.add("programming");
        uniqueTags.add("tutorial");
        uniqueTags.add("java"); // Duplicate will be ignored
        System.out.println("Unique Tags:");
        for (String tag : uniqueTags) {
            System.out.println("- " + tag);
        }
    }
}

(Possible Output - order may vary)

Unique Tags:
- java
- tutorial
- programming

When to Use for-each vs. The Traditional for Loop

The for-each loop is great, but it's not a one-size-fits-all solution. Here’s a comparison to help you choose.

Feature for-each Loop Traditional for Loop
Readability Excellent. Very clear and concise. Good. More verbose, but all loop variables are in one place.
Modification Cannot modify the collection while iterating (will throw ConcurrentModificationException). Can modify the collection if you use the iterator's remove() method.
Index Access No. You cannot get the index of the current element. Yes. You have direct access to the index (i).
Bidirectional No. You can only iterate forward. Yes. You can loop forwards (i++) and backwards (i--).
Iteration Subset No. You must iterate over the entire collection. Yes. You can loop over a specific range (for (int i = 2; i < 5; ...)).

Important Limitations and Caveats

a) The ConcurrentModificationException

You cannot add or remove elements from a collection while iterating over it with a for-each loop. This is because the loop uses an iterator, and modifying the collection directly invalidates the iterator.

import java.util.ArrayList;
import java.util.List;
public class ConcurrentModificationExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie"));
        // This will throw a ConcurrentModificationException!
        for (String name : names) {
            if (name.equals("Bob")) {
                names.remove(name); // DO NOT DO THIS
            }
        }
    }
}

Solutions:

  1. Use the traditional for loop: This gives you more control.
    for (int i = 0; i < names.size(); i++) {
        if (names.get(i).equals("Bob")) {
            names.remove(i);
            i--; // Important: decrement the index because the list shifted
        }
    }
  2. Use the iterator's remove() method: This is the safest and most correct way.
    Iterator<String> iterator = names.iterator();
    while (iterator.hasNext()) {
        String name = iterator.next();
        if (name.equals("Bob")) {
            iterator.remove(); // Safe removal
        }
    }

b) Cannot Get the Index

If you need the index of the current element (e.g., to print "Item 1: Apple"), the for-each loop is not the right tool. Use the traditional for loop or an IntStream with forEach.

// Traditional for loop (best for index)
List<String> items = Arrays.asList("Apple", "Banana", "Cherry");
for (int i = 0; i < items.size(); i++) {
    System.out.println("Item " + (i + 1) + ": " + items.get(i));
}
// Using IntStream (Java 8+)
IntStream.range(0, items.size()).forEach(i -> {
    System.out.println("Item " + (i + 1) + ": " + items.get(i));
});

Java 8+: The forEach() Method with Lambdas

For those using Java 8 or later, the forEach() method is another powerful and often preferred way to iterate, especially when combined with lambda expressions or method references.

forEach() on a Collection

import java.util.Arrays;
import java.util.List;
public class ForEachMethodExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        // Using a lambda expression
        System.out.println("Using Lambda:");
        names.forEach(name -> System.out.println(name));
        // Using a method reference (more concise)
        System.out.println("\nUsing Method Reference:");
        names.forEach(System.out::println);
    }
}

forEach() on a Stream

The forEach method is also a terminal operation on streams, which is very powerful for data processing pipelines.

import java.util.Arrays;
import java.util.List;
public class StreamForEachExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // Filter even numbers and print them
        numbers.stream()
               .filter(n -> n % 2 == 0) // Keep only even numbers
               .forEach(System.out::println); // Print each one
    }
}

Output:

2
4
6
8
10

Summary: Which One Should You Use?

| Your Goal | Recommended Loop | | :--- | :--- | :--- | | Iterate through all elements of a collection or array and don't need the index. | for-each loop. It's the most readable and idiomatic choice. | | Need the index of the current element. | Traditional for loop. | | Need to add or remove elements from the collection while iterating. | Traditional for loop (with caution) or use the iterator's remove() method. | | Need to iterate backwards or over a specific range. | Traditional for loop. | | Are working with a Stream for complex data processing (filter, map, reduce). | stream().forEach(...). |

分享:
扫描分享到社交APP
上一篇
下一篇