Java 在多重映射中,如何返回出现率最高的值
我有番石榴图书馆的多重地图Java 在多重映射中,如何返回出现率最高的值,java,collections,guava,multimap,Java,Collections,Guava,Multimap,我有番石榴图书馆的多重地图 Multimap<Integer,String> maps = ArrayListMultimap.create(); maps.put(1, "foo"); maps.put(1, "bar"); maps.put(1, "foo"); maps.put(2, "Hello"); maps.put(2, "
Multimap<Integer,String> maps = ArrayListMultimap.create();
maps.put(1, "foo");
maps.put(1, "bar");
maps.put(1, "foo");
maps.put(2, "Hello");
maps.put(2, "foo");
maps.put(2, "World");
maps.put(2, "World");
我试过了
Stream result1 = maps.keySet().stream()
.map(i ->
maps.get(i).stream()
.collect(
Collectors.groupingBy(v -> v, Collectors.counting())
)
);
结果:
{{bar=1, foo=2}=1, {Hello=1, foo=1, World=2}=1}
您似乎在寻找的内容可以在迭代条目时实现,如下所示:
Map<Integer, String> integerStringMap = maps.asMap()
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> mostFrequentWord(e.getValue())));
maps.keySet().stream().distinct().collect(收集器)toMap(键->键,键->{
Map valueByCount=maps.get(key.stream().collect(Collectors.groupingBy(s->s,Collectors.counting());
返回值ByCount.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue))
.map(map.Entry::getKey)
.orElse(空);
}));
您可以执行以下操作:
var valueFrequency = maps.entries().stream()
.collect(groupingBy(Function.identity(), counting()));
var result = valueFrequency.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.stream()
.flatMap(maxFreq -> valueFrequency.entrySet().stream()
.filter(val -> val.getValue().equals(maxFreq.getValue()))
.map(Map.Entry::getKey))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
这不会是一个非常艰难的过程。显然,您首先需要按键分组。然后根据该
键
,您需要找到相应值
的最大出现次数(例如,对于1==foo
)。找到max
的唯一方法是遍历映射到某个键的集合。由于您使用的是Multimap
,因此这会使事情变得更加复杂,您可以很容易地获得以下内容:
maps.put(1, "foo");
maps.put(1, "bar");
maps.put(1, "bar");
maps.put(1, "foo");
因此,在海事组织,这可以写成:
Map<Integer, List<String>> result =
maps.keySet()
.stream()
.collect(Collectors.toMap(
Function.identity(),
x -> {
Map<String, Long> freqMap = maps.get(x)
.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting())
);
long max = Collections.max(freqMap.values());
return freqMap.entrySet()
.stream()
.filter(y -> y.getValue() == max)
.map(Entry::getKey)
.collect(Collectors.toList());
}
));
映射结果=
maps.keySet()
.stream()
.collect(collector.toMap)(
Function.identity(),
x->{
Map freqMap=maps.get(x)
.stream()
.collect(收集器.groupingBy(
Function.identity(),
Collectors.counting())
);
long max=Collections.max(freqMap.values());
return freqMap.entrySet()
.stream()
.filter(y->y.getValue()==max)
.map(条目::getKey)
.collect(Collectors.toList());
}
));
- 我按
Key
(1
和2
)第一组
- 然后获取映射到该键的
集合
- 然后计算表示值频率的
Map
。例如:[“foo”=2];[“条”=1]
- 然后,我查看出现的最大次数。由于您使用的是多重映射,因此可能出现以下情况:
[“foo”=2];[“bar”=2]
,对于相同的键
,因此我们需要将foo
和bar
作为结果
- 基于该
max
,我找到了相应的值
不含溪流,但使用番石榴,如:
@测试
public void应在MultiMapValues()中找到Rights Stoccurrences{
//给定
Multimap maps=ArrayListMultimap.create();
地图.put(1,“foo”);
地图。放置(1,“条形”);
地图.put(1,“foo”);
放(2,“你好”);
地图.put(2,“foo”);
地图。put(2,“世界”);
地图。put(2,“世界”);
//什么时候
Map result=ImmutableMap.copyOf(Maps.transformValues(Maps.asMap(),this::findHighestOccurrence));
//然后
断言(结果)。仅包含(
条目(1,“foo”),
条目(2,“世界”);
}
私有字符串findHighestOccurrence(集合值){
返回Multisets.copyHighestCountFirst(ImmutableMultiset.copyOf(values)).iterator().next();
}
如果存在MultisetMultimap子类型(即,Map
——与专用的Multimap
一样,在这种情况下,它可能是存储数据的最佳结构。使用流进行操作是错误的。根据定义,流应该是无状态的,元素集上的操作应该相互独立。在这里,您需要计算发生次数,然后执行一些操作基于单一数据流中的数据。您使用的是哪种多重映射?我的意思是我从哪个库添加了番石榴标签。@liquidpie只是为了进一步澄清这个问题,当两个值的频率相同时(例如foo=2
和bar=2
),您希望得到什么样的响应?您希望输出结果是Map
还是Map
?这里最频繁的单词是什么?@Amongalen虽然我认为命名会有帮助,但也会用代码更新。再添加一个Map。put(1,“bar”)
对于用户已经拥有的任何东西…@Eugene和foo
或bar
(两者都符合条件)在结果中出现…您的解决方案所建议的进一步与问题的期望相矛盾,我引用我需要返回出现次数最高的值…(值和非值)…进一步[1,foo][2,世界]
而不是[1,[foo]][2,[World]]
@Naman你是对的,毫无疑问,我认为OP也没有考虑这个案例,尽管这可能是一种可能性。
var valueFrequency = maps.entries().stream()
.collect(groupingBy(Function.identity(), counting()));
var result = valueFrequency.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.stream()
.flatMap(maxFreq -> valueFrequency.entrySet().stream()
.filter(val -> val.getValue().equals(maxFreq.getValue()))
.map(Map.Entry::getKey))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
maps.put(1, "foo");
maps.put(1, "bar");
maps.put(1, "bar");
maps.put(1, "foo");
Map<Integer, List<String>> result =
maps.keySet()
.stream()
.collect(Collectors.toMap(
Function.identity(),
x -> {
Map<String, Long> freqMap = maps.get(x)
.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting())
);
long max = Collections.max(freqMap.values());
return freqMap.entrySet()
.stream()
.filter(y -> y.getValue() == max)
.map(Entry::getKey)
.collect(Collectors.toList());
}
));
@Test
public void shouldFindHightestOccurrencesInMultimapValues() {
//given
Multimap<Integer, String> maps = ArrayListMultimap.create();
maps.put(1, "foo");
maps.put(1, "bar");
maps.put(1, "foo");
maps.put(2, "Hello");
maps.put(2, "foo");
maps.put(2, "World");
maps.put(2, "World");
//when
Map<Integer, String> result = ImmutableMap.copyOf(Maps.transformValues(maps.asMap(), this::findHighestOccurrence));
//then
assertThat(result).containsOnly(
entry(1, "foo"),
entry(2, "World"));
}
private String findHighestOccurrence(Collection<String> values) {
return Multisets.copyHighestCountFirst(ImmutableMultiset.copyOf(values)).iterator().next();
}