文本内容每行是name;value
格式,先上代码
public class ReadTxt {
public static void main(String[] args) throws Exception {
var start = System.currentTimeMillis();
calculate();
System.err.format("Took %,d ms\n", System.currentTimeMillis() - start);
}
private static void calculate() throws Exception {
var allStats = new BufferedReader(new FileReader("measurements.txt"))
.lines()
.parallel()
.collect(
groupingBy(line -> line.substring(0, line.indexOf(';')),
summarizingDouble(line ->
parseDouble(line.substring(line.indexOf(';') + 1)))));
var result = allStats.entrySet().stream().collect(Collectors.toMap(
Entry::getKey,
e -> {
var stats = e.getValue();
return String.format("%.1f/%.1f/%.1f",
stats.getMin(), stats.getAverage(), stats.getMax());
},
(l, r) -> r,
TreeMap::new));
System.out.println(result);
}
}
解析
这段代码是一个Java方法,其主功能是从一个文本文件中读取数据,按照特定的规则进行分组和统计,然后输出每组数据的最小值、平均值和最大值。下面详细解析这个方法的每个步骤:
-
文件读取与流处理:
var allStats = new BufferedReader(new FileReader("measurements.txt")) .lines() .parallel() .collect(...
- 这段代码首先创建了一个
BufferedReader
对象来读取名为measurements.txt
的文件。 lines()
方法将这个文件转换为一个流(Stream
),其中每个元素代表文件中的一行。parallel()
方法的调用使得接下来的流操作可以并行执行,这可能提高处理大文件时的性能。
- 这段代码首先创建了一个
-
数据分组与统计:
collect(groupingBy(line -> line.substring(0, line.indexOf(';')), summarizingDouble(line -> Double.parseDouble(line.substring(line.indexOf(';') + 1)))));
- 这段代码使用
collect
方法对流中的元素进行收集。 groupingBy
函数用于根据提供的分类函数对元素进行分组。在这里,分类函数是根据每行数据中;
字符前的内容来分组,即假设每行数据的格式为key;value
,则按key
来分组。summarizingDouble
函数用于生成包含统计信息的DoubleSummaryStatistics
对象,这里是针对每个分组的value
部分(即;
字符后的内容),并将其从字符串转换为双精度浮点数(Double
)。
- 这段代码使用
-
结果处理与格式化输出:
var result = allStats.entrySet().stream().collect(Collectors.toMap( Entry::getKey, e -> { var stats = e.getValue(); return String.format("%.1f/%.1f/%.1f", stats.getMin(), stats.getAverage(), stats.getMax()); }, (l, r) -> r, TreeMap::new)); System.out.println(result);
- 这段代码处理上一步得到的分组统计结果
allStats
。 - 使用
entrySet().stream()
转换分组统计结果为流,然后通过collect
方法收集处理后的数据。 Collectors.toMap
方法用于生成一个映射,其键是分组的键(即每行数据中;
前的内容),值是格式化后的字符串,包含每组数据的最小值、平均值和最大值,格式为最小值/平均值/最大值
。- 在冲突的情况下(即两个键相同),选择右边的值(
(l, r) -> r
),尽管在这个场景中不太可能出现键的冲突。 - 使用
TreeMap::new
作为收集器的最后一个参数,确保结果是根据键(分组标识)排序的。
- 这段代码处理上一步得到的分组统计结果
-
打印结果:
System.out.println(result);
语句用于打印处理和格式化后的结果。
这个方法从名为measurements.txt
的文件中读取数据,按行进行处理,根据每行中;
前的内容进行分组,然后计算每个分组中数值(;
后的内容)的最小值、平均值和最大值,并按分组键的自然顺序打印出这些统计结果。