简体   繁体   English

使用 Java 的 lambda 和流将文本文件映射到 Map

[英]Mapping a text file to a Map using Java's lambda and streams

So my text file contains 5 fields, i would like to create a Map<Pair<String, String>,List<List<String>>> from of it, where Pair is an instance of Apache's ImmutablePair having 2 of the 5 fields as key, the value of that Map would be a List<List<String>> where each List<String> for the key, would contain the remaining 3 fields, so if the file would be like:所以我的文本文件包含 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

The result Map would be like:结果 Map 将类似于:

K:(A,B)
 V:((1,2,3),(3,4,5))
K:(A,C)
 V:((4,5,9),(5,6,7))

I am trying to achieve this by making as much as possible use of lambdas and streams, here is my temporary code,, which works, but it returns as value the entire line:我试图通过尽可能多地使用 lambdas 和流来实现这一点,这是我的临时代码,它有效,但它以整行的值返回:

  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;
  }

This call to Collectors.groupingBy makes use of this implmentation, which defaults to returning the map values as List<T> but what i would like and i cannot find is returning a sublist, to save space in memory.这个对Collectors.groupingBy的调用利用了这个实现,它默认将 map 值返回为List<T>但我想要但我找不到的是返回一个子列表,以节省 memory 中的空间。
I was under the impression that this is the right method, as the description says...正如描述所说,我的印象是是正确的方法......
"and then performing a reduction operation on the values associated with a given key using the specified downstream Collector." “然后使用指定的下游收集器对与给定键关联的值执行缩减操作。”
Is just cant find a pre made Collector where i can specify the code to finalize the list.只是找不到预制的收集器,我可以在其中指定代码以完成列表。
Anyone has any tip?任何人有任何提示?

Collectors#mapping would do the work for you. 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) {}

And Output would be like this,而 Output 会是这样的,

{(A,C)=[[4, 5, 9], [5, 6, 7]], (A,B)=[[1, 2, 3], [3, 4, 5]]}

Pair is tuple from apache commons-lang library. Pair是来自 apache commons-lang 库的元组。 Using here just to hold values.在这里使用只是为了保存值。 You can use any other object for that purpose.为此,您可以使用任何其他 object。

alternatively, can be written like this as well或者,也可以这样写

.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())));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM