将Map <file,file =“”>转换为Map <file,list <file =“”>&gt;使用java 8 stream

时间:2018-04-06 14:32:05

标签: java dictionary java-8

我有一些我保存在Map中的属性文件。例如:

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

我想将Map<String, String>转换为

Map<String, List<String>> map = new HashMap<>(); 

那应该是

<"One", ("1", "4")>
<"Two", ("2", "3")>

我有一些我想用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;
  }

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

1 个答案:

答案 0 :(得分: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())));
}

即。获取所有filesWithTskFile,过滤掉Map中密钥不在files中的条目。然后将Map分组为value

使用

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

一个更通用的例子,有:

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

运行:

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

给出:

A->[3, 1]
B->[2, 4]

扩展为:

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

跑步:

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

给予:

A->[1, 3]

NB:我使用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())));
}