Как получить ключ от карты, связанной с другим списком - PullRequest
0 голосов
/ 01 октября 2019

Мне нужно создать карту, связав 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); });
            }

Приведенный выше код завершается ошибкой, если список содержит несколькоЗначения принадлежат одному ключу из-за дублирования. Например,

Карта ввода > - {"Fruit" -> ["apple", "orange"], "Animal" -> ["cat", "dog"]}

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

выходная карта как {"Fruit" -> "apple","Animal" -> "cat"} ("dog" is overriden by "cat")

Есть ли способ получить вывод как

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

Есть ли способ добиться этого более аккуратно и точноспособ

1 Ответ

0 голосов
/ 01 октября 2019

Поскольку ваш тип вывода 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>.

...