使用java 8流将Map <File,File>转换为Map <File,List <File >>

Pav*_*hov 3 java dictionary java-8

我有一些属性文件,我保存在地图中.例:

Map<String, String> map = new HashMap<>();
map.put("1", "One");
map.put("2", "Two");
map.put("3", "Two");
map.put("4", "One"); 
Run Code Online (Sandbox Code Playgroud)

我想转换Map<String, String>

Map<String, List<String>> map = new HashMap<>(); 
Run Code Online (Sandbox Code Playgroud)

那应该是

<"One", ("1", "4")>
<"Two", ("2", "3")>
Run Code Online (Sandbox Code Playgroud)

我有一些代码,我想用Java 8风格重写.

  private Map<File, List<File>> getAllFiles(Set<File> files) {
   Map<File, File> inputFilesWithTskFile = 
   AppStorage.getInstance().getApplicationBean().getInputFilesWithTskFile();

    List<File> tsks = new ArrayList<>();
    for (Map.Entry<File, File> entry : inputFilesWithTskFile.entrySet()) {
        if (files.contains(entry.getKey())) {
            tsks.add(entry.getValue());
        }
    }
    Map<File, List<File>> listTsk = new HashMap<>();
    for (Map.Entry<File, File> entry : inputFilesWithTskFile.entrySet()) {
        if (tsks.contains(entry.getValue())) {
            List<File> files1 = listTsk.get(entry.getValue());
            if (files1 == null) {
                files1 = new ArrayList<>();
            }
            files1.add(entry.getKey());
            listTsk.put(entry.getValue(), files1);
        }
    }
    return listTsk;
  }
Run Code Online (Sandbox Code Playgroud)

感谢您的任何帮助.也许你知道一些教程解释如何从Map创建左侧应该有值的Map,右侧应该是按值分组的键列表.

Bor*_*der 8

类似于以下内容:

private Map<File, List<File>> getAllFiles(List<File> files) {
    return AppStorage.getInstance().getApplicationBean().getInputFilesWithTskFile()
            .entrySet()
            .stream()
            .filter(e -> files.contains(e.getKey()))
            .collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toList())));
}
Run Code Online (Sandbox Code Playgroud)

即得到所有filesWithTskFile,过滤掉Map键不在的位置files.然后组Mapvalue.


运用

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
Run Code Online (Sandbox Code Playgroud)

一个更通用的例子,包括:

public static Map<String, List<String>> groupByValue(final Map<String, String> input) {
    return input.entrySet().stream()
            .collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toList())));
}
Run Code Online (Sandbox Code Playgroud)

运行:

final Map<String, String> example = Map.of(
        "1", "A",
        "2", "B",
        "3", "A",
        "4", "B"
        );

groupByValue(example).forEach((k, v) -> System.out.printf("%s->%s%n", k, v));
Run Code Online (Sandbox Code Playgroud)

得到:

A->[3, 1]
B->[2, 4]
Run Code Online (Sandbox Code Playgroud)

扩展到:

public static Map<String, List<String>> groupByValue(final Map<String, String> input, final Set<String> take) {
    return input.entrySet().stream()
            .filter(e -> take.contains(e.getKey()))
            .collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toList())));
}
Run Code Online (Sandbox Code Playgroud)

并运行:

groupByValue(example, Set.of("1", "3")).forEach((k, v) -> System.out.printf("%s->%s%n", k, v));
Run Code Online (Sandbox Code Playgroud)

得到:

A->[1, 3]
Run Code Online (Sandbox Code Playgroud)

注意:我使用了一个Set而不是一个List过滤器.一个Set保证其contains方法将运行O(1),而对于List将在运行O(n).所以List非常低效的.根据输入的大小,实际上最好将您复制List到过滤Set 之前:

private Map<File, List<File>> getAllFiles(List<File> files) {
    final Set<File> filter = Set.copyOf(files);
    return AppStorage.getInstance().getApplicationBean().getInputFilesWithTskFile()
            .entrySet()
            .stream()
            .filter(e -> filter.contains(e.getKey()))
            .collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toList())));
}
Run Code Online (Sandbox Code Playgroud)