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();
      }