给定一个HashMap,如何根据Java中的重复值过滤它



我有一个哈希映射,我需要过滤该映射或仅使用给定映射中包含重复值的键创建映射。请建议我们如何实现这一目标?

请注意,给定的输入只是地图。并且没有其他要搜索的值。

      Map map = new HashMap();
         map.put(1, "abc");
         map.put(2, "def");
         map.put(3, "mno");
         map.put(4, "abc");
         map.put(5, "ijk");
         map.put(6, "abc");
      Map result = new HashMap();
          (1, "abc")
          (4, "abc")
          (6, "abc");

我期待一个包含所有具有重复值的键的新映射

您可以使用流执行此操作。

首先,将条目组合在一起,使具有相同值的条目组合在一起:

Map<String, Map.Entry<Integer, String>> grouped =
    map.entrySet().stream()
       .collect(groupingBy(Map.Entry::getValue));

然后删除仅出现 1 次值的条目:

grouped.values().removeIf(m -> m.size() <= 1);

然后再次展平条目:

Map<Integer, String> result = grouped.values().stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

您也可以在单个表达式中执行此操作:

Map<Integer, String> grouped =
    map.entrySet().stream()
        .collect(groupingBy(Map.Entry::getValue))
        .values().stream()
        .filter(m -> m.size() > 1)
        .map(Map::entrySet)
        .flatMap(Collection::stream)
        .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

您可以创建从值到其频率的映射

Map<V, Long> counts = map.values().stream()
    .collect(Collectors.groupingBy(
        Function.identity(), Collectors.counting()));

然后过滤原始地图的条目流,保留计数大于 1 的元素,并从中创建新地图:

Map<K, V> result = map.entrySet().stream()
    .filter(e -> counts.get(e.getValue()) > 1)
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

下面是一个示例:

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
public class RetainFrequentValues
{
    public static void main(String[] args)
    {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "abc");
        map.put(2, "def");
        map.put(3, "mno");
        map.put(4, "abc");
        map.put(5, "ijk");
        map.put(6, "abc");
        // For testing
        map.put(7, "def");
        Map<Integer, String> result = retainFrequentValues(map);
        result.entrySet().forEach(System.out::println);
    }
    private static <K, V> Map<K, V> retainFrequentValues(Map<K, V> map)
    {
        Map<V, Long> counts = map.values().stream()
            .collect(Collectors.groupingBy(
                Function.identity(), Collectors.counting()));
        Map<K, V> result = map.entrySet().stream()
            .filter(e -> counts.get(e.getValue()) > 1)
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
        return result;
    }
}

利用谷歌的番石榴收藏:

进口:

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Maps;

用法:

Map<Integer, String> map = new HashMap<>();
map.put(1, "abc");
map.put(2, "def");
map.put(3, "mno");
map.put(4, "abc");
map.put(5, "ijk");
map.put(6, "abc");
HashMultiset<String> ms = HashMultiset.create();
ms.addAll(map.values());
ms.removeIf(e -> ms.count(e) == 1);
Map<Integer, String> result = Maps.filterValues(map, ms::contains);

结果:{1=abc, 4=abc, 6=abc}

如果番石榴不是一种选择,请参阅上面的答案之一。

最新更新