从地图中提取没有重复值的键

时间:2019-09-06 09:16:42

标签: java java-8

地图定义为:

 Map<Integer,String> map = new HashMap<>();
        map.put(2,"ram");
        map.put(3,"ram");
        map.put(4,"gopal");
        map.put(5,"madan");
        map.put(6,"shyam");
        map.put(7,"gopal");
        map.put(8,"ram");

我的预期输出是List,其中仅包含没有重复值的键。

5
6

我的方法和思考过程:

思考过程1:

我先获取map.entrySet().stream().map(....),然后再获取map中的另一个流,并过滤存在重复值的值。

这种方法很快就浪费了,因为将在嵌套流中再次比较第一个索引值,因此我碰巧会过滤掉所有元素。

思考过程2

我将值保留在不同的List中:

List<String> subList = map.entrySet().stream()
        .map((k)->k.getValue())
        .collect(Collectors.toList());

然后:

    map.entrySet().stream()
            .filter(s ->
                subList.contains(s.getValue())                )
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());

但是我得到的输出为

2
3
4
5
6
7
8

输出很明显,因为我从流中选择的值是 s ,我正在池中比较它,该值将至少一次出现。

然后我再次考虑到,如果我可以拥有一个可以计数的计数器,并且该值存在,那么它将递增,但是现在一切似乎都非常模糊。

我可以使用流通过索引进行迭代的任何方式,这样我就可以始终保留所取的键值,并与其余值进行比较。

很想简短地解释一下。

2 个答案:

答案 0 :(得分:1)

在创建1时,可以使用频率subList过滤值,例如:

Set<String> uniqueSet = map.values().stream()
        .collect(Collectors.groupingBy(a -> a, Collectors.counting()))
        .entrySet().stream()
        .filter(a -> a.getValue() == 1)
        .map((Map.Entry::getKey))
        .collect(Collectors.toSet());

,然后执行与以下操作相同的操作:

Set<Integer> result = map.entrySet().stream()
        .filter(e -> uniqueSet.contains(e.getValue()))
        .map(Map.Entry::getKey)
        .collect(Collectors.toSet());

或者正如Holger在评论中指出的那样,您可以取消使用counting值来过滤唯一值,而不是Boolean

Set<String> uniqueSet = map.values().stream()
        .collect(Collectors.toMap(Function.identity(), v -> true, (a,b) -> false))
        .entrySet().stream()
        .filter(Map.Entry::getValue)
        .map((Map.Entry::getKey))
        .collect(Collectors.toSet());

答案 1 :(得分:1)

您可以将任务分为两步。由groupingBy()counting()收集器重复的第一个计数值。

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

其结果是:

  

{madan = 1,shyam = 1,gopal = 2,ram = 3}

第二步是仅查找其值不重复的键。因此,您可以使用filter()并按上一步结果过滤地图。

map.entrySet()
   .stream()
   .filter(entry -> valueCount.get(entry.getValue())==1).map(Map.Entry::getKey)
   .collect(Collectors.toList())