能否将迭代器遍历与BufferedReader读取的两种while逻辑合并为单个while?
Absolutely! You can merge these two distinct reading patterns into one consistent while loop by leveraging Java's Iterable and Iterator interfaces to abstract away the underlying data source. This lets you treat both the file reader and the list as a uniform sequence of strings, no more branching logic. Here's how to pull it off:
Core Idea: Abstract with Iterable<String>
The key is to wrap both your BufferedReader and List<String> into an Iterable<String> instance. This gives you a single Iterator<String> for either source, so you can use the same while (iterator.hasNext()) loop for both cases.
Step 1: Build a Custom Iterable for BufferedReader
First, create an Iterable implementation that handles line-by-line reading from a BufferedReader:
import java.io.BufferedReader; import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; public class BufferedReaderIterable implements Iterable<String> { private final BufferedReader reader; public BufferedReaderIterable(BufferedReader reader) { this.reader = reader; } @Override public Iterator<String> iterator() { return new Iterator<String>() { private String nextLine; @Override public boolean hasNext() { if (nextLine == null) { try { nextLine = reader.readLine(); } catch (IOException e) { throw new RuntimeException("Failed to read line from file", e); } } return nextLine != null; } @Override public String next() { if (!hasNext()) { throw new NoSuchElementException("No more lines to read"); } String currentLine = nextLine; nextLine = null; // Reset to fetch next line on next hasNext() call return currentLine; } }; } }
Step 2: Unify Your Reading Logic
Now, instead of checking if the list is null and branching, you just pick the right Iterable based on your data source, then use a single while loop:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class UnifiedReaderExample { private static final String DEST2 = "your-file-path.txt"; private static final Charset charset = Charset.defaultCharset(); public static void main(String[] args) { // Your original data sources List<String> list = new ArrayList<>(); // Could be null or populated BufferedReader reader1 = new BufferedReader(new InputStreamReader(new FileInputStream(DEST2), charset)); // Select the appropriate data source Iterable<String> dataSource; if (list != null && !list.isEmpty()) { dataSource = list; // List already implements Iterable } else { dataSource = new BufferedReaderIterable(reader1); } // Single while loop for both scenarios! Iterator<String> iterator = dataSource.iterator(); while (iterator.hasNext()) { String line = iterator.next(); // Process your line here System.out.println(line); } // Clean up resources properly try { reader1.close(); } catch (IOException e) { e.printStackTrace(); } } }
Bonus: Even Cleaner with For-Each Loop
Since we're using Iterable, you can skip the explicit while loop entirely and use a for-each loop for better readability:
for (String line : dataSource) { // Process your line System.out.println(line); }
Important Notes
- Resource Safety: Use try-with-resources to auto-close the
BufferedReader(avoids manual cleanup mistakes):try (BufferedReader reader1 = new BufferedReader(new InputStreamReader(new FileInputStream(DEST2), charset))) { Iterable<String> dataSource = list != null && !list.isEmpty() ? list : new BufferedReaderIterable(reader1); for (String line : dataSource) { // Process line } } catch (IOException e) { e.printStackTrace(); } - Null/Empty List Handling: Adjust the condition
list != null && !list.isEmpty()to match your needs. If a non-null but empty list should still fall back to the file reader, keep the!list.isEmpty()check; if not, just uselist != null.
内容的提问来源于stack exchange,提问作者heavywar

