Back to Stream: map & Transform
Q17Question 17 of 34

Convert a list of CSV lines ("name,department,salary") into a List<Employee> by splitting each line and constructing objects inside map()

Key Concepts
  • map() can parse each raw CSV line by splitting it and constructing a typed domain object from the pieces
  • Always use BigDecimal for money parsing, never double, to avoid rounding errors
  • Trim each token after splitting because CSV files often have stray whitespace after commas
  • A malformed line with too few fields throws ArrayIndexOutOfBoundsException
  • Naive comma-splitting breaks if a field itself contains a comma; use a proper CSV library for real data
  • For robust pipelines, validate each line and route bad rows to an error list instead of crashing

Definition

`map` can parse each raw line by splitting it and constructing a typed object from the pieces.
  • Parsing map: transforms each raw CSV string into a structured domain object.
  • Split and construct: line.split(",") gives a token array; each token is trimmed, parsed, and passed to the constructor.
  • Money: always parse salary into BigDecimal, never double.
  • Defensive parsing: validate field count and catch parse errors to prevent pipeline crashes.
  • CSV limitation: naive splitting on comma breaks if a field itself contains a comma; use OpenCSV for real data.

The data-entry clerk at the National Bank of India receives a plain text file where each line is "Rajesh,Loans,95000". She reads each line, chops it at the commas, and fills in a proper employee form with the pieces. map doing the split-and-construct is exactly that.

Understanding the Concepts

What does a parsing map do?

The mapping function receives a CSV line and must produce an Employee. First it splits the line with line.split(","), which returns a String array of tokens. For the format name, department, salary: index 0 is the name, index 1 is the department, and index 2 is the salary text that still needs converting to a number.

How do you parse CSV lines into Employee objects?

JAVA
package com.bank.hr;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

public class CsvToEmployee {
    public static void main(String[] args) {
        List<String> csvLines = List.of(
            "Rajesh, Loans, 95000",
            "Priya, IT, 120000",
            "Amit, Finance, 85000");

        List<Employee> employees = csvLines.stream()
            .map(line -> {
                String[] parts = line.split(",");
                return new Employee(
                    parts[0].trim(),
                    parts[1].trim(),
                    new BigDecimal(parts[2].trim()));
            })
            .collect(Collectors.toList());

        employees.forEach(e -> System.out.printf("%s (%s) - Rs. %s%n",
            e.getName(), e.getDepartment(), e.getSalary().toPlainString()));
    }
}
TEXT
Rajesh (Loans) - Rs. 95000
Priya (IT) - Rs. 120000
Amit (Finance) - Rs. 85000

Why use BigDecimal for the salary?

Salary is money, and double arithmetic is not exact. Adding many doubles accumulates rounding error. BigDecimal is exact.

JAVA
// WRONG: double loses precision
double salary = Double.parseDouble("95000.10"); // may not be exactly 95000.10

// CORRECT: BigDecimal is exact
BigDecimal salary = new BigDecimal("95000.10"); // exactly 95000.10

What are common mistakes?

Mistake: not trimming tokens, leading to parsing failures or corrupt data.

JAVA
// WRONG: stray spaces cause NumberFormatException
String line = "Rajesh, Loans, 95000";
String[] parts = line.split(",");
new BigDecimal(parts[2]); // " 95000" has a leading space → exception!

// CORRECT: trim each token
new BigDecimal(parts[2].trim()); // "95000" → parses correctly

How do you handle malformed lines?

A line with too few fields throws ArrayIndexOutOfBoundsException. In production, validate each line and either skip bad rows or route them to an error list.

JAVA
List<String> errors = new java.util.ArrayList<>();

List<Employee> employees = csvLines.stream()
    .map(line -> {
        try {
            String[] parts = line.split(",");
            if (parts.length < 3) throw new IllegalArgumentException("Too few fields");
            return new Employee(
                parts[0].trim(), parts[1].trim(),
                new BigDecimal(parts[2].trim()));
        } catch (Exception ex) {
            errors.add(line + " → " + ex.getMessage());
            return null;
        }
    })
    .filter(java.util.Objects::nonNull)
    .collect(Collectors.toList());

if (!errors.isEmpty()) {
    System.err.println("Bad rows: " + errors);
}

Why is naive comma-splitting dangerous?

Naive splitting on comma breaks if a field itself contains a comma, for example a department written as "Sales, North". Real CSV uses quoting rules.

| Input line | Naive split result | Problem |
|---|---|---|
| Rajesh,Loans,95000 | [Rajesh, Loans, 95000] | Correct |
| Rajesh,"Sales, North",95000 | [Rajesh, "Sales, North", 95000] | Wrong: 4 tokens |

For anything beyond trivial input, use a proper CSV library such as OpenCSV or Apache Commons CSV.

What about the reverse operation?

See Q2242 for converting employees back to CSV lines. A round-trip test (parse then serialise should reproduce the original line) is the fastest way to catch formatting bugs.

What should a senior engineer know?

  • Always trim tokens from CSV data; stray whitespace is the most common cause of parse failures in banking file imports.
  • For money, use new BigDecimal(String), never new BigDecimal(double), because the double constructor introduces representation error.
  • In production, wrap the parse in try-catch and route errors to an audit table rather than crashing the whole pipeline.
  • For real CSV, use OpenCSV or Apache Commons CSV to handle quoting, escaping, and multi-line fields.

What are common interview follow-up questions?

  • "Why BigDecimal instead of double for money?" double is not exact for many decimal fractions.
  • "How do you handle malformed lines?" Validate, skip, and route to an error list.
  • "What if a field contains a comma?" Use a proper CSV library with quoting support.

Visual Overview

DIAGRAM
  CSV line: "Rajesh, Loans, 95000"
       │
       │  split(",")
       ▼
  String[]: ["Rajesh", " Loans", " 95000"]
       │
       │  trim each token
       ▼
  ["Rajesh", "Loans", "95000"]
       │
       │  new Employee(name, dept, new BigDecimal(salary))
       ▼
  Employee("Rajesh", "Loans", 95000)

  Repeated for each line → List<Employee>

Key Takeaway

To turn raw CSV lines into structured objects I use a parsing map, where the function splits each line on the comma, trims every token, converts each piece to its proper type, and constructs the domain object. Each line yields exactly one Employee, so the stream goes from strings to employees, which I collect into a list.

In my banking project at the National Bank of India this was the nightly import from an external HR vendor. The crucial detail was parsing the salary into a BigDecimal rather than a double, and trimming every token, because the vendor's file often had stray spaces.

I always validate each line and route bad rows to an error list rather than crashing the pipeline, because a malformed line with too few fields throws ArrayIndexOutOfBoundsException. For anything beyond trivial input I use a proper CSV library like OpenCSV, because naive comma-splitting breaks the moment a field contains a comma.

Remember one sentence: split, trim, parse with BigDecimal for money, and guard against malformed lines to safely convert CSV into domain objects with map.

---

Share
Use ← → arrow keys to navigate