使用 Java 的 lambda 和流将文本文件映射到地图
Mapping a text file to a Map using Java's lambda and streams
所以我的文本文件包含 5 个字段,我想创建一个 Map<Pair<String, String>,List<List<String>>>
从中,Pair 是 Apache ImmutablePair
的一个实例,有 5 个字段中的 2 个作为键,该 Map 的值将是一个 List<List<String>>
,其中每个 List<String>
作为键,将包含剩余的 3 个字段,所以如果文件是这样的:
A,B,1,2,3
A,C,4,5,9
A,B,3,4,5
A,C,5,6,7
结果地图如下:
K:(A,B)
V:((1,2,3),(3,4,5))
K:(A,C)
V:((4,5,9),(5,6,7))
我试图通过尽可能多地使用 lambda 和流来实现这一点,这是我的临时代码,它有效,但它 returns 整行的价值:
private Map<Pair<String, String>, List<List<String>>> createMultimapFromFile() {
Map<Pair<String, String>, List<List<String>>> map = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME)))
.lines()
.map(line -> Arrays.asList(line.split(COMMA)))
.filter(lineAsList -> lineAsList.size() == REQUIRED_FILE_LINE_LENGTH)
.collect(Collectors.groupingBy(filteredLine ->
ImmutablePair.of(filteredLine.get(1), filteredLine.get(2))));
return map;
}
对 Collectors.groupingBy
的调用使用了 this 实现,它默认将地图值返回为 List<T>
但我想要但找不到的是返回一个子列表,将 space 保存在内存中。
正如描述所说,我的印象是 this 是正确的方法...
"and then performing a reduction operation on the values associated with a given key using the specified downstream Collector."
就是找不到预制的收集器,我可以在其中指定代码来完成列表。
有人有什么建议吗?
Collectors#mapping
会为您完成这项工作。
try(BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME), "utf-8"))) {
return reader.lines()
.map(line -> line.split(","))
.filter(lineAsList -> lineAsList.length == REQUIRED_FILE_LINE_LENGTH)
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
} catch (Exception e) {}
输出会是这样的,
{(A,C)=[[4, 5, 9], [5, 6, 7]], (A,B)=[[1, 2, 3], [3, 4, 5]]}
Pair
是来自 apache commons-lang 库的元组。在这里使用只是为了保持价值。您可以为此目的使用任何其他对象。
也可以这样写
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
//without pair
.collect(Collectors.groupingBy(data -> ImmutablePair.of(data[0], data[1]), Collectors.mapping(data -> Arrays.asList(data[2], data[3], data[4]), Collectors.toList())));
所以我的文本文件包含 5 个字段,我想创建一个 Map<Pair<String, String>,List<List<String>>>
从中,Pair 是 Apache ImmutablePair
的一个实例,有 5 个字段中的 2 个作为键,该 Map 的值将是一个 List<List<String>>
,其中每个 List<String>
作为键,将包含剩余的 3 个字段,所以如果文件是这样的:
A,B,1,2,3
A,C,4,5,9
A,B,3,4,5
A,C,5,6,7
结果地图如下:
K:(A,B)
V:((1,2,3),(3,4,5))
K:(A,C)
V:((4,5,9),(5,6,7))
我试图通过尽可能多地使用 lambda 和流来实现这一点,这是我的临时代码,它有效,但它 returns 整行的价值:
private Map<Pair<String, String>, List<List<String>>> createMultimapFromFile() {
Map<Pair<String, String>, List<List<String>>> map = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME)))
.lines()
.map(line -> Arrays.asList(line.split(COMMA)))
.filter(lineAsList -> lineAsList.size() == REQUIRED_FILE_LINE_LENGTH)
.collect(Collectors.groupingBy(filteredLine ->
ImmutablePair.of(filteredLine.get(1), filteredLine.get(2))));
return map;
}
对 Collectors.groupingBy
的调用使用了 this 实现,它默认将地图值返回为 List<T>
但我想要但找不到的是返回一个子列表,将 space 保存在内存中。
正如描述所说,我的印象是 this 是正确的方法...
"and then performing a reduction operation on the values associated with a given key using the specified downstream Collector."
就是找不到预制的收集器,我可以在其中指定代码来完成列表。
有人有什么建议吗?
Collectors#mapping
会为您完成这项工作。
try(BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME), "utf-8"))) {
return reader.lines()
.map(line -> line.split(","))
.filter(lineAsList -> lineAsList.length == REQUIRED_FILE_LINE_LENGTH)
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
} catch (Exception e) {}
输出会是这样的,
{(A,C)=[[4, 5, 9], [5, 6, 7]], (A,B)=[[1, 2, 3], [3, 4, 5]]}
Pair
是来自 apache commons-lang 库的元组。在这里使用只是为了保持价值。您可以为此目的使用任何其他对象。
也可以这样写
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
//without pair
.collect(Collectors.groupingBy(data -> ImmutablePair.of(data[0], data[1]), Collectors.mapping(data -> Arrays.asList(data[2], data[3], data[4]), Collectors.toList())));