如何使用Stream API读取CSV文件并构建Planet类对象?
Using Java Stream API to Read CSV and Build Planet Objects
First, let's complete the Planet class (since your original code was cut off) to give full context:
import java.util.List; public class Planet { private String name; private long inhabitants; private boolean stargateAvailable; private boolean dhdAvailable; private List<String> teamsVisited; public Planet(String name, long inhabitants, boolean stargateAvailable, boolean dhdAvailable, List<String> teamsVisited) { this.name = name; this.inhabitants = inhabitants; this.stargateAvailable = stargateAvailable; this.dhdAvailable = dhdAvailable; this.teamsVisited = teamsVisited; } // Getters as provided public String getName() { return name; } public long getInhabitants() { return inhabitants; } public boolean isStargateAvailable() { return stargateAvailable; } public boolean isDhdAvailable() { return dhdAvailable; } public List<String> getTeamsVisited() { return teamsVisited; } }
Below are two approaches to achieve your goal—one for simple CSVs, and a more robust option for complex cases:
Option 1: Manual CSV Parsing (No External Libraries)
This works great if your CSV doesn’t have tricky edge cases like commas inside quoted values.
Step-by-Step Code
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class PlanetCsvReader { public static void main(String[] args) { String csvFilePath = "path/to/your/planets.csv"; try { List<Planet> planets = Files.lines(Paths.get(csvFilePath)) // Skip the header row (remove this if your CSV has no header) .skip(1) // Map each line to a Planet object .map(line -> { String[] fields = line.split(","); // Ensure we have exactly 5 fields (adjust if your CSV structure differs) if (fields.length != 5) { throw new IllegalArgumentException("Invalid line format: " + line); } String name = fields[0].trim(); long inhabitants = Long.parseLong(fields[1].trim()); boolean stargateAvailable = Boolean.parseBoolean(fields[2].trim()); boolean dhdAvailable = Boolean.parseBoolean(fields[3].trim()); // Split the teams string into a list (e.g., "SG-1;SG-Atlantis" → ["SG-1", "SG-Atlantis"]) List<String> teamsVisited = Arrays.stream(fields[4].trim().split(";")) .map(String::trim) .collect(Collectors.toList()); return new Planet(name, inhabitants, stargateAvailable, dhdAvailable, teamsVisited); }) .collect(Collectors.toList()); // Example usage: Print all planet names planets.forEach(planet -> System.out.println("Loaded planet: " + planet.getName())); } catch (IOException e) { System.err.println("Failed to read CSV file: " + e.getMessage()); } catch (NumberFormatException e) { System.err.println("Invalid number format in CSV: " + e.getMessage()); } catch (IllegalArgumentException e) { System.err.println("Malformed CSV line: " + e.getMessage()); } } }
Quick Notes
- Header Handling: Use
.skip(1)if your CSV starts with a header (e.g.,Name,Inhabitants,StargateAvailable,DhdAvailable,TeamsVisited). - Field Separators: Adjust the split character (
,) if your CSV uses a different delimiter like;. - Teams List: I used
;to separate teams (since the main CSV uses commas). Update this to match your actual data format.
Option 2: Using OpenCSV (Robust for Complex CSVs)
If your CSV has quoted fields with commas (e.g., "P3X-777, The Lost Planet",1000,true,false,"SG-1,SG-Atlantis"), manual parsing will break. Use OpenCSV to handle these edge cases properly.
Step 1: Add OpenCSV Dependency (Maven)
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> <!-- Use the latest stable version --> </dependency>
Step 2: Stream API with OpenCSV
import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvException; import java.io.FileReader; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class PlanetCsvReaderWithOpenCSV { public static void main(String[] args) { String csvFilePath = "path/to/your/planets.csv"; try (CSVReader reader = new CSVReader(new FileReader(csvFilePath))) { List<Planet> planets = reader.readAll() .stream() // Skip header row .skip(1) .map(fields -> { String name = fields[0].trim(); long inhabitants = Long.parseLong(fields[1].trim()); boolean stargateAvailable = Boolean.parseBoolean(fields[2].trim()); boolean dhdAvailable = Boolean.parseBoolean(fields[3].trim()); List<String> teamsVisited = Arrays.stream(fields[4].trim().split(";")) .map(String::trim) .collect(Collectors.toList()); return new Planet(name, inhabitants, stargateAvailable, dhdAvailable, teamsVisited); }) .collect(Collectors.toList()); planets.forEach(planet -> System.out.println("Loaded planet: " + planet.getName())); } catch (IOException e) { System.err.println("Failed to read CSV file: " + e.getMessage()); } catch (CsvException e) { System.err.println("CSV parsing error: " + e.getMessage()); } catch (NumberFormatException e) { System.err.println("Invalid number format in CSV: " + e.getMessage()); } } }
Quick Notes
- Quoted Field Support: OpenCSV automatically handles commas inside quoted fields, so you don’t have to worry about broken splits.
- Resource Management: Uses try-with-resources to ensure the
CSVReaderis closed properly. - Error Handling: Catches
CsvExceptionfor CSV-specific issues like malformed quotes.
Key Takeaways
- Stick to manual parsing only for simple, well-structured CSVs.
- For production code or complex data, always use a dedicated library like OpenCSV to avoid subtle bugs.
- The Stream API keeps the code concise and readable, letting you chain operations like skipping headers, mapping lines to objects, and collecting results in a single pipeline.
内容的提问来源于stack exchange,提问作者NewishToProgramming
相关产品推荐
相关产品推荐

