如何从与另一个列表关联的地图中获取密钥

时间:2019-10-01 06:16:15

标签: java collections java-8

我需要通过将List 与Map >的键相关联来创建地图,如下所示。

 Input Map< String,List< String>>  - {"Fruit" -> ["apple","orange"], "Animal" -> ["cat","dog"]}

Input List< String> - {"apple","dog","xyzzy"}

output map as {"Fruit" -> "apple","Animal" -> "dog"} by discarding unmatching entries like "xyzzy" in this case" 


```
Map <String, String> outputMap = new HashMap<>();
Map <String, String> tempMap = new HashMap<>();

for (Map.Entry<String, List<String>> entry : inputMap.entrySet()) {
      entry.getValue().forEach(value -> tempMap.put(value, entry.getKey()));
   }    

 inputList.forEach(value ->
            {   
             if(tempMap.get(value)!=null)
             outputMap.put(tempMap.get(value),value); });
            }

如果由于重复,列表包含多个值属于同一键,则上述代码将失败。例如

输入图>-{“水果”-> [“苹果”,“橙色”],“动物”-> [“猫”,“狗”]}

Input List< String> - {"apple","dog","cat"}

将地图输出为{"Fruit" -> "apple","Animal" -> "cat"} ("dog" is overriden by "cat")

有没有一种方法可以获取输出

{"Fruit" -> "apple","Animal" -> "dog", "Animal" -> "cat"}

有没有办法以更整洁和精确的方式实现这一目标?

1 个答案:

答案 0 :(得分:0)

由于您的输出类型为Map<String, List<String>>,因此无法获取输出

{"Fruit" -> "apple","Animal" -> "dog", "Animal" -> "cat"}

({String “动物” key,不能重复)

但是,如果要过滤输入地图以检查包含列表,可以执行以下操作:

final Map<String, List<String>> inputMap = new HashMap<>();
inputMap.put("Fruit", asList("apple", "orange"));
inputMap.put("Animal", asList("cat", "dog"));

final List<String> list = asList("apple", "dog", "cat");

final Map<String, List<String>> outputMap = inputMap.entrySet().stream()
        .filter(e -> e.getValue().stream().anyMatch(list::contains))
        .collect(toMap(e -> e.getKey(), e -> e.getValue().stream().filter(list::contains).collect(toList())));

outputMap.forEach((k, v) -> System.out.printf("%s: %s%n", k, v));

输出:

Fruit: [apple]
Animal: [cat, dog]

两次过滤遍历两次,根据输入映射的方式,这将是好是坏。无论如何,不​​需要重新分组;如果输入匹配比例很高,则可以执行以下操作:

final Map<String, List<String>> outputMap = inputMap.entrySet().stream()
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue().stream().filter(list::contains).collect(toList())))
        .filter(e -> !e.getValue().isEmpty())
        .collect(toMap(e -> e.getKey(), e -> e.getValue()));

一个不直接相关的问题是,为了提高性能,最好将过滤器列表定义为Set<String>