如何改造Java加载CSV到ArrayList的代码为可复用通用逻辑
实现思路
- 核心是把通用CSV读取逻辑和不同实体的行数据转换逻辑分离:文件读取、跳过表头、遍历行这些逻辑是所有CSV加载场景通用的,把「每行字符串数组转成对应实体对象」这部分差异逻辑抽出来作为参数传入即可。
- 利用Java泛型让工具类支持返回任意类型的实体集合,不需要针对每个实体单独写加载类。
- 用
Function<String[], T>函数式接口接收不同实体的转换逻辑,不用额外定义自定义接口,适配性更高。
改写后的可复用代码
首先是通用加载工具类:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.function.Function; public class LoadingData { // 泛型方法,传入文件名和行转换函数,返回对应类型的实体集合 public static <T> ArrayList<T> loadCsv(String fileName, Function<String[], T> lineConverter) { ArrayList<T> resultList = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(fileName))) { String currentLine; while ((currentLine = br.readLine()) != null) { String[] detailed = currentLine.split(","); // 统一跳过表头行 if(detailed[0].equals("id")) continue; // 调用传入的转换逻辑生成实体,加入结果集 resultList.add(lineConverter.apply(detailed)); } } catch (IOException ioe) { ioe.printStackTrace(); } return resultList; } }
使用示例
// 加载图书数据,仅需传入图书实体的转换逻辑 ArrayList<Book> books = LoadingData.loadCsv("books.csv", detailed -> { String id = detailed[0]; String title = detailed[3]; String firstName = detailed[1]; String lastName = detailed [2]; String genre = detailed [4]; return new Book(id, title, firstName, lastName, genre); }); // 加载客户账户数据,仅需传入客户实体的转换逻辑,核心加载代码完全复用 ArrayList<Reader> readers = LoadingData.loadCsv("readers.csv", detailed -> { // 按Reader类的字段顺序从数组取对应值即可 String readerId = detailed[0]; String account = detailed[1]; String phone = detailed[2]; // 其他Reader需要的字段可自行补充 return new Reader(readerId, account, phone); });
后续新增其他CSV加载需求时,只需要编写对应实体的行转换逻辑即可,不需要修改核心加载代码。
内容的提问来源于stack exchange,提问作者David Espiño
相关产品推荐
相关产品推荐

