将 Map 中的重复值映射到它们所在的键

Mapping duplicate values from Map against the keys in which they are found

我有的是,

Map<String, String> map = new HashMap<>();
map.put("Shop1", "Product1");
map.put("Shop2", "Product2");
map.put("Shop3", "Product1");
map.put("Shop4", "Product2");
map.put("Shop5", "Product3");

我想要的是,

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

其中result包含,

产品 1 -> 店铺 1,店铺 3

Product2 -> Shop2,Shop4

这里 Product1 在商店 Shop1 和 Shop3 中多次被发现,Product2 在商店 Shop2 和 Shop4 中多次被发现。任何帮助将不胜感激。

您要做的是反转映射(值变成键,键按旧值分组)。应该有这样做的图书馆,但是一个带有流的示例解决方案:

result = map.entrySet()
.stream()
.filter(e -> Collections.frequency(map.values(), e.getValue()) > 1)
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))

您可以使用 Guava's Multimap 来做到这一点。

final Map<String, String> map = new HashMap<>();
map.put("Shop1", "Product1");
map.put("Shop2", "Product2");
map.put("Shop3", "Product1");
map.put("Shop4", "Product2");
map.put("Shop5", "Product3");

final Multimap<String, String> shopToProduct = Multimaps.forMap(map), productToShop = HashMultimap.create();

Multimaps.invertFrom(shopToProduct, productToShop);

// Prints the output you want
productToShop.asMap().entrySet().forEach(System.out::println);

// You can also get the backing map, but ideally use the Multimap abstraction
final Map<String, Collection<String>> backingMap = productToShop.asMap();

首先找到 distinct 个值。之后,您可以遍历每个值并在地图上搜索它们的 key,每当您找到 key 时,只需将它们放入 list.

List<String> list = map.values().stream().distinct().collect(Collectors.toList()); //Collecting the distinct values
for (String value : list) {  //iterating through each key
    List<String> temp =  map.entrySet()
             .stream()
             .filter(entry -> value.equals(entry.getValue())) //filtering out similar entries
             .map(Map.Entry::getKey)
             .collect(Collectors.toList());
     result.put(value, temp);
 }
 System.out.println(result);

您可以使用 Guava 的 Multimap 来实现此目的,但是您需要反转地图。

Multimap<String, String> map = HashMultimap.create();
map.put("Product1", "Shop1");
map.put("Product2", "Shop2");
map.put("Product2", "Shop1");
map.put("Product2", "Shop4");
map.put("Product3", "Shop5");
System.out.println(map.get("Product2")); // [Shop4, Shop1, Shop2]

或者,如果您不想反转原始地图 - 您可以使用 Map<String, List<String>(或将以下解决方案与上面的 Multimap 结合使用)并使用 [=14 添加记录=],然后反转地图以获得您想要的值。

        Map<String, List<String>> map = new HashMap<>();
        map.computeIfAbsent("Shop1", (x) -> new ArrayList<>()).add("Product1");
        map.computeIfAbsent("Shop2", (x) -> new ArrayList<>()).add("Product2");
        map.computeIfAbsent("Shop3", (x) -> new ArrayList<>()).add("Product1");
        map.computeIfAbsent("Shop4", (x) -> new ArrayList<>()).add("Product2");
        map.computeIfAbsent("Shop5", (x) -> new ArrayList<>()).add("Product3");
        // Invert the map
        Map<String, List<String>> invertedMap = map
                .entrySet()
                .stream()
                .collect(HashMap::new, (m, entry) -> {
                    entry.getValue().forEach((value) -> {
                        m.computeIfAbsent(value, (x) -> new ArrayList<>()).add(entry.getKey());
                    });
                }, Map::putAll);

        System.out.println(invertedMap); // {Product3=[Shop5], Product1=[Shop1, Shop3], Product2=[Shop4, Shop2]}