Definition
- Serialising map: turns each
Employeeback into a single comma-separated string. toPlainString()on BigDecimal avoids scientific notation for very large numbers.- Round-trip symmetry: parse then serialise should reproduce the original line, and vice versa.
- Escaping: if a field could contain the delimiter, use proper CSV quoting or a library.
- File output: collect the CSV lines into a list, then write with
Files.write()orBufferedWriter.
The clerk at the National Bank of India now has filled employee forms and must send them back out as plain text, one line per person like "Rajesh,Loans,95000". She reads each form and writes its fields on a line separated by commas.
Understanding the Concepts
How do you serialise employees back to CSV?
The mapping function takes an Employee and returns one CSV string. The simplest form joins the fields directly.
package com.bank.hr;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
public class EmployeeToCsv {
public static void main(String[] args) {
List<Employee> staff = List.of(
new Employee("Rajesh", "Loans", new BigDecimal("95000")),
new Employee("Priya", "IT", new BigDecimal("120000")),
new Employee("Amit", "Finance", new BigDecimal("85000")));
List<String> csvLines = staff.stream()
.map(e -> e.getName() + "," + e.getDepartment() + ","
+ e.getSalary().toPlainString())
.collect(Collectors.toList());
csvLines.forEach(System.out::println);
}
}
Rajesh,Loans,95000
Priya,IT,120000
Amit,Finance,85000
Why use toPlainString for BigDecimal?
BigDecimal.toString() can produce scientific notation for very large or very small values, for example 1.2E+8 instead of 120000000. toPlainString() always produces the full decimal form.
BigDecimal big = new BigDecimal("120000000");
System.out.println(big.toString()); // might be 1.2E+8
System.out.println(big.toPlainString()); // always 120000000
How do you write the CSV to a file?
import java.nio.file.Files;
import java.nio.file.Path;
String header = "name,department,salary";
List<String> allLines = new java.util.ArrayList<>();
allLines.add(header);
allLines.addAll(csvLines);
Files.write(Path.of("employees.csv"), allLines);
System.out.println("Written " + csvLines.size() + " data rows.");
What is a round-trip test and why does it matter?
| Direction | Test | |---|---| | Parse then serialise | Original CSV line → Employee → CSV line (should match original) | | Serialise then parse | Employee → CSV line → Employee (should match original) |
// Round-trip test
String original = "Rajesh,Loans,95000";
Employee parsed = parseLine(original);
String serialised = toCSV(parsed);
assert original.equals(serialised) : "Round-trip failed!";
A round-trip property is the quickest way to catch a formatting or escaping bug before it corrupts an export.
What are common mistakes?
Mistake: not escaping fields that contain the delimiter.
// WRONG: department "Sales, North" breaks the row
Employee e = new Employee("Rajesh", "Sales, North", new BigDecimal("95000"));
String csv = e.getName() + "," + e.getDepartment() + "," + e.getSalary();
// "Rajesh,Sales, North,95000" → 4 columns instead of 3!
// CORRECT: quote fields that contain the delimiter
String safeCsv = e.getName() + ",\"" + e.getDepartment() + "\"," + e.getSalary();
// "Rajesh,\"Sales, North\",95000" → correct 3 columns
For anything beyond trivial data, use a proper CSV library like OpenCSV.
What about using String.join?
// Cleaner alternative with String.join
List<String> csvLines = staff.stream()
.map(e -> String.join(",",
e.getName(), e.getDepartment(), e.getSalary().toPlainString()))
.collect(Collectors.toList());
What should a senior engineer know?
- Serialisation and parsing must be symmetric and tested together.
- For money, use
toPlainString()to avoid scientific notation. - For data not guaranteed delimiter-free, use a proper CSV library with quoting and escaping.
- The source list is never mutated; map produces a new stream of CSV strings.
What are common interview follow-up questions?
- "How do you handle fields with commas?" Use CSV quoting or a library.
- "How do you write the result to a file?" Use
Files.write(path, lines). - "What is a round-trip test?" Parsing and serialising should be inverse operations.
Visual Overview
Employee("Rajesh", "Loans", 95000)
│
│ map(e -> name + "," + dept + "," + salary.toPlainString())
▼
String: "Rajesh,Loans,95000"
Employee("Priya", "IT", 120000)
│
│ map(e -> ...)
▼
String: "Priya,IT,120000"
Collected → List<String>
["Rajesh,Loans,95000", "Priya,IT,120000", "Amit,Finance,85000"]
│
│ Files.write(path, lines)
▼
employees.csv on disk
Key Takeaway
To serialise structured objects back into CSV I use a map whose function joins each object's fields with commas, so the stream goes from employees to strings, one row per employee. For the salary I render it with toPlainString() so the output never slips into scientific notation.
In my banking project at the National Bank of India this was the nightly export to a partner system that only accepts plain CSV. It is the exact reverse of the import.
The most important quality check is the round-trip test: parsing a line and serialising it again should reproduce the original, and serialising an object and parsing it back should reproduce the original object. For data that is not guaranteed delimiter-free I use a proper CSV library for quoting and escaping.
Remember one sentence: map(e -> name + "," + dept + "," + salary.toPlainString()) serialises each employee to a CSV row, and a round-trip test verifies correctness.
---