Java中如何使用Stream流对CSV文件按日期时间字段排序
解决方案
完全可以通过Stream流实现按日期时间排序的需求,你只需要在现有过滤逻辑之后增加排序步骤即可,另外你的代码里还有两处需要先修正的问题:
- 日期格式定义错误:你示例的日期分隔符是
.,但你写的SimpleDateFormat模式用了/,且24小时制时间需要用HH而非12小时制的hh,同时YYYY代表周年,常规年份应该用yyyy。另外SimpleDateFormat是线程不安全的,更推荐用Java 8及以上版本提供的DateTimeFormatter。 - 流关闭方式不推荐:手动调用
close()容易在出现异常时无法正常关闭流,建议用try-with-resources语法自动管理流的关闭。
完整可运行代码(Java 8+通用版)
推荐先把每行数据封装成实体类再排序,避免排序过程中重复解析日期损耗性能:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.stream.Stream; public class Logfilereader { // 定义和你日期格式匹配的格式化器,线程安全可全局复用 private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); // 自定义实体类存储每行CSV数据,Java 16+可以直接用record更简洁 static class CsvLine { LocalDateTime datetime; int seq; String type; String value; String unit; public CsvLine(LocalDateTime datetime, int seq, String type, String value, String unit) { this.datetime = datetime; this.seq = seq; this.type = type; this.value = value; this.unit = unit; } } public static void main(String[] args) throws IOException { // try-with-resources自动关闭流,不需要手动close try (Stream<String> rows1 = Files.lines(Path.of("C:\\Users\\julit\\IdeaProjects\\Logfilereader\\src\\testdata1.csv"))) { rows1 .map(x -> x.split(";")) .filter(x -> x.length == 5) .filter(x -> Integer.parseInt(x[1]) >= 0) .filter(x -> "HYGRO".equals(x[2]) || "TEMP".equals(x[2])) .filter(x -> "CELSIUS".equals(x[4]) || "PERCENT".equals(x[4])) // 把数组转成实体类,提前解析好日期避免排序时重复解析 .map(arr -> new CsvLine( LocalDateTime.parse(arr[0], DATE_TIME_FORMATTER), Integer.parseInt(arr[1]), arr[2], arr[3], arr[4] )) // 按日期时间升序排序,要降序的话加.reversed()即可 .sorted((o1, o2) -> o1.datetime.compareTo(o2.datetime)) // 输出结果 .forEach(line -> System.out.printf("%s %s %s %s %s%n", line.datetime.format(DATE_TIME_FORMATTER), line.seq, line.type, line.value, line.unit )); } } }
小文件轻量实现方案(无需定义实体类)
如果你的CSV文件体积很小,不想额外定义实体类,也可以直接在排序阶段实时解析日期,缺点是排序过程中会重复解析日期,性能较差:
// 省略前面相同的过滤逻辑,直接替换sorted和后续输出部分即可 .sorted((arr1, arr2) -> { LocalDateTime time1 = LocalDateTime.parse(arr1[0], DATE_TIME_FORMATTER); LocalDateTime time2 = LocalDateTime.parse(arr2[0], DATE_TIME_FORMATTER); return time1.compareTo(time2); }) .forEach(x -> System.out.println(x[0]+ " "+x[1]+" " +x[2]+ " "+x[3]+ " "+ x[4]));
内容的提问来源于stack exchange,提问作者Julius Tscherch
相关产品推荐
相关产品推荐

