用java中的streams和lambda查找(树)映射中的所有最大值

用java中的streams和lambda查找(树)映射中的所有最大值,java,lambda,java-stream,treemap,Java,Lambda,Java Stream,Treemap,因此,我必须在java中使用streams和lambda查找映射中的最大值。查找一个最大值不是问题,但如何查找多个最大值? 例子: 元素e=2,i=1,a=2的树形图, 我目前的解决方案是a=2,但我想要a=2,e=2 我的代码: Map<String, Integer> frequencies = new Treemap<>(); frequencies.put("e", 2);//I don't put the values in like thi

因此,我必须在java中使用streams和lambda查找映射中的最大值。查找一个最大值不是问题,但如何查找多个最大值? 例子: 元素e=2,i=1,a=2的树形图, 我目前的解决方案是a=2,但我想要a=2,e=2

我的代码:

Map<String, Integer> frequencies = new Treemap<>();
frequencies.put("e", 2);//I don't put the values in like this but it'll do to test
frequencies.put("i", 1);
frequencies.put("a", 2);
Optional<Map.Entry<String, Integer>> maxEntry = frequencies.entrySet().stream()
        .max(Map.Entry.comparingByValue());//frequencies is the TreeMap<String, Integer>
//I know this only searches one max value, here's my other attempt:
try (Stream<Map.Entry<String, Integer>> stream = frequencies.entrySet().stream()) {
      stream
          .sorted(Map.Entry.comparingByValue())
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k, v) -> k, LinkedHashMap::new));
//I don't know what to do here, I somehow would have to get the result into a new list, but it still only returns one result
    }

如果我做错了什么,请告诉我。

首先,找到最大频率:

Optional<Integer> maxFreqOptional = frequencies.values()
    .stream()
    .max(Comparator.naturalOrder());
然后,您可以将此频率作为一个值来收集所有条目:

Integer maxFreq = maxFreqOptional.get(); // check if it's empty first
List<String> mostFrequent = frequencies.entrySet()
    .stream()
    .filter(entry -> entry.getValue().equals(maxFreq))
    .map(Map.Entry<String, Integer>::getKey)
    .collect(Collectors.toList());

首先,找到最大频率:

Optional<Integer> maxFreqOptional = frequencies.values()
    .stream()
    .max(Comparator.naturalOrder());
然后,您可以将此频率作为一个值来收集所有条目:

Integer maxFreq = maxFreqOptional.get(); // check if it's empty first
List<String> mostFrequent = frequencies.entrySet()
    .stream()
    .filter(entry -> entry.getValue().equals(maxFreq))
    .map(Map.Entry<String, Integer>::getKey)
    .collect(Collectors.toList());
你就快到了:

使用value=frequency作为键,原始键作为值,将入口流收集到树映射中。因此,请使用级联分组方式。然后获取具有最大键的条目:

TreeMap<Integer, List<String>> map = frequencies.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry<String, Integer>::getValue, TreeMap::new, Collectors.toList()
    ));
Map.Entry<Integer, List<String>> largest = map.lastEntry();
注意:如果您的数据集很大,并且您希望避免构建此反向映射,则您可能更喜欢其他建议的解决方案之一,该解决方案将映射迭代两次:一次查找最大频率,然后再次查找所有相应的条目。

您几乎做到了:

使用value=frequency作为键,原始键作为值,将入口流收集到树映射中。因此,请使用级联分组方式。然后获取具有最大键的条目:

TreeMap<Integer, List<String>> map = frequencies.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry<String, Integer>::getValue, TreeMap::new, Collectors.toList()
    ));
Map.Entry<Integer, List<String>> largest = map.lastEntry();
注意:如果您的数据集很大,并且希望避免构建此反向映射,则您可能更喜欢其他建议的解决方案之一,该解决方案将映射迭代两次:一次查找最大频率,然后再次查找所有相应的条目。

如果存在,您可以按maxEntry的值进行筛选,以获得所有映射。最大值的条目

List<Map.Entry<String, Integer>> res = frequencies.entrySet().stream()
                                 .filter(e -> e.getValue().equals(maxEntry.get().getValue()))
                                 .collect(Collectors.toList());
在线演示

输出:[a=2,e=2]

如果存在,您可以按maxEntry的值进行筛选,以获得所有映射。最大值的输入

List<Map.Entry<String, Integer>> res = frequencies.entrySet().stream()
                                 .filter(e -> e.getValue().equals(maxEntry.get().getValue()))
                                 .collect(Collectors.toList());
在线演示

输出:[a=2,e=2]

因此,我必须在java中使用streams和lambda查找映射中的最大值

这里有一种不用树映射的方法。它对包含的条目进行频率计数

Map<String, Integer> map = Map.of("z", -1, "b", 0, "r", -2,
        "s", 0, "j", 1, "a", 2, "i", 1, "e", 2);

Optional<Entry<Integer, List<Entry<String,Integer>>>> opt = map.entrySet()
        .stream()
        .collect(Collectors.groupingBy(Entry::getValue))
        .entrySet().stream().max(Entry.comparingByKey());

System.out.println(opt.isPresent() ? opt.get().getValue() : "Empty List");

为了好玩,你可以绕过初始地图,创建一个条目流。实际上,当您创建初始贴图时,您正在创建入口对象,因此这里不涉及额外的贴图开销

        
Builder<Entry<String, Integer>> entryStream = Stream.builder();

entryStream.add(Map.entry("b", 0));
entryStream.add(Map.entry("r", -2));
entryStream.add(Map.entry("s", 0));
entryStream.add(Map.entry("j", 1));
entryStream.add(Map.entry("a", 2));
entryStream.add(Map.entry("i", 1));
entryStream.add(Map.entry("e", 2));

因此,我必须在java中使用streams和lambda查找映射中的最大值

这里有一种不用树映射的方法。它对包含的条目进行频率计数

Map<String, Integer> map = Map.of("z", -1, "b", 0, "r", -2,
        "s", 0, "j", 1, "a", 2, "i", 1, "e", 2);

Optional<Entry<Integer, List<Entry<String,Integer>>>> opt = map.entrySet()
        .stream()
        .collect(Collectors.groupingBy(Entry::getValue))
        .entrySet().stream().max(Entry.comparingByKey());

System.out.println(opt.isPresent() ? opt.get().getValue() : "Empty List");

为了好玩,你可以绕过初始地图,创建一个条目流。实际上,当您创建初始贴图时,您正在创建入口对象,因此这里不涉及额外的贴图开销

        
Builder<Entry<String, Integer>> entryStream = Stream.builder();

entryStream.add(Map.entry("b", 0));
entryStream.add(Map.entry("r", -2));
entryStream.add(Map.entry("s", 0));
entryStream.add(Map.entry("j", 1));
entryStream.add(Map.entry("a", 2));
entryStream.add(Map.entry("i", 1));
entryStream.add(Map.entry("e", 2));


因为您只需要匹配最大值的条目,所以将映射的所有条目分组到反向映射中并没有任何好处。您只需放弃其值与最大值不匹配的所有条目

以下是使用lambdas的一种简洁方法:

Integer max = frequencies.isEmpty() ? 
              Integer.MIN_VALUE :
              Collections.max(frequencies.values());

List<String> result = new ArrayList<>();
frequencies.forEach((k, v) -> { if (v.equals(max)) result.add(k); });

因为您只需要匹配最大值的条目,所以将映射的所有条目分组到反向映射中并没有任何好处。您只需放弃其值与最大值不匹配的所有条目

以下是使用lambdas的一种简洁方法:

Integer max = frequencies.isEmpty() ? 
              Integer.MIN_VALUE :
              Collections.max(frequencies.values());

List<String> result = new ArrayList<>();
frequencies.forEach((k, v) -> { if (v.equals(max)) result.add(k); });
.collectCollectors.groupingByMap.Entry::getValue,Collectors.mappingMap.Entry::getKey,Collectors.toList仅供参考这是树映射,不是树映射…再次收集到树映射并获取所需结果的最后一个条目..collectCollectors.groupingByMap.Entry::getValue,Collectors.mappingMap.Entry::getKey,Collectors.toList仅供参考,这是TreeMap,而不是TreeMap…再次收集到TreeMap并获取所需结果的最后条目。@fps谢谢。这是Collectors.GroupingBy如果没有映射,这应该可以真正用于生成树映射。@fps谢谢。它是Collectors.GroupingBy如果没有映射,这应该可以真正用于生成树映射。