地图定义为:
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 ,我正在池中比较它,该值将至少一次出现。
然后我再次考虑到,如果我可以拥有一个可以计数的计数器,并且该值存在,那么它将递增,但是现在一切似乎都非常模糊。
我可以使用流通过索引进行迭代的任何方式,这样我就可以始终保留所取的键值,并与其余值进行比较。
很想简短地解释一下。
答案 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())