如何使用 lambda 从列表中查找最大数字及其出现次数?

请在下面找到一个代码,该代码计算流中数字的出现次数,并返回一个映射,其中数字作为键,值作为其在流中的出现次数:

Map<Integer, Long> collect = Stream.of(1, 2, 3, 4, 4, 55555, 12)
                .collect(groupingBy(Function.identity(), counting()));

如何将生成的地图限制为仅最大数字(或在出现平局时为数字)?


慕丝7291255
浏览 184回答 4
4回答

慕码人8056858

看看这个简单的例子:public static void getMeNumbersWithHighestFrequence3(int[] numbers, int howMany) {&nbsp; &nbsp; Map<Integer, Long> collect = IntStream.of(numbers).boxed().collect(groupingBy(Function.identity(), TreeMap::new, counting())).descendingMap().entrySet().stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .limit(howMany)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(TreeMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), Map::putAll);}您还可以通过放置过滤器值以某种方式搜索它们,它将采用键值大于该值的所有条目,如下所示:&nbsp; public static void getMeNumbersWithHighestFrequenceByFilterNumber(int[] numbers, int value) {&nbsp; &nbsp; &nbsp; &nbsp; Map<Integer, Long> collect = IntStream.of(numbers).boxed().collect(groupingBy(Function.identity(), TreeMap::new, counting())).descendingMap().headMap(value, true);&nbsp; &nbsp; }用法简单:public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; int[] numbers = {1, 2, 3, 4, 4, 55555, 12};&nbsp; &nbsp; &nbsp; &nbsp; getMeNumbersWithHighestFrequence(numbers, 5);&nbsp; &nbsp; }

青春有我

我建议您使用StreamEx中定义的算盘或我的库算盘工具:MoreCollectorsint result = Stream.of(1, 2, 12, 3, 4, 4, 55555, 12)&nbsp; &nbsp; .collect(MoreCollectors.maxAll(MoreCollectors.countingInt()));// map resultMap<Integer, Integer> mapResult = Stream.of(1, 2, 12, 3, 4, 4, 55555, 12)&nbsp; &nbsp; .collect(maxAll(groupingBy(Function.identity(), countingInt())));因为你可能想要:1)所有最大数字的总和,或2)将它们映射到其他东西,或3)...更多。不需要也不应该只为一个特定的用户案例编写这种特定的代码。(如果你想知道如何实现它,只需下载库的源代码或反编译类。它们发布在阿帕奇许可证 v2 上)更新。实际上,如果你在谈论数字,我认为这可能是一个错误的问题,因为传统的数字比使用lambdas更简单,更有效:for-loopint[] nums = {1, 2, 12, 3, 4, 4, 55555, 12, 55555};int[] result = {Integer.MIN_VALUE, 0}; // [0] is the largest number if [1] (occurrence) is bigger than 0.for (int num : nums) {&nbsp; if (num > result[0]) {&nbsp; &nbsp; result[0] = num;&nbsp; &nbsp; result[1] = 1;&nbsp; } else if (num == result[0]) {&nbsp; &nbsp; result[1]++;&nbsp; }}System.out.println(result[0] + ": " + result[1]);如果您必须使用流/Lambdas:int[] result = IntStream.of(nums).collect(() -> new int[] {Integer.MIN_VALUE, 0}, (a, num) -> {&nbsp; if (num > a[0]) {&nbsp; &nbsp; a[0] = num;&nbsp; &nbsp; a[1] = 1;&nbsp; } else if (num == a[0]) {&nbsp; &nbsp; a[1]++;&nbsp; }}, (a1, a2) -> {&nbsp; if (a1[0] == a2[0]) {&nbsp; &nbsp; a1[1] += a2[1];&nbsp; } else if (a1[0] < a2[0]) {&nbsp; &nbsp; a1[1] = a2[1];&nbsp; }});System.out.println(result[0] + ": " + result[1]);

鸿蒙传说

我希望有人能想出一个更简单的解决方案:&nbsp;List<Entry<Integer, Long>> list =&nbsp; &nbsp; &nbsp; &nbsp; List.of(3, 3, 4, 4, 5, 5, 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .entrySet()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .sorted(Map.Entry.<Integer, Long>comparingByValue().reversed())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());&nbsp; &nbsp; Map<Integer, Long> result = new HashMap<>();&nbsp; &nbsp; Iterator<Entry<Integer, Long>> iter = list.iterator();&nbsp; &nbsp; Entry<Integer, Long> left;&nbsp; &nbsp; Entry<Integer, Long> right = null;&nbsp; &nbsp; while (iter.hasNext()) {&nbsp; &nbsp; &nbsp; &nbsp; left = iter.next();&nbsp; &nbsp; &nbsp; &nbsp; if (right == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.put(left.getKey(), left.getValue());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (iter.hasNext() && (right = iter.next()).getValue().longValue() == left.getValue()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.put(right.getKey(), right.getValue());&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }因此,首先将它们收集到您已经拥有的同一张地图上。然后按值对它们进行排序;然后迭代该结果,并仅获取那些处于最开始并与其值匹配的结果。这个想法是,由于这些已经按值排序: - 我们只需要迭代,只要重复,只要没有这样的匹配,我们就完成了(因为它们是排序的,因此任何后面的元素只会更小)。3 = 2; 4 = 2; 5 = 2; 1 = 12!= 2

慕婉清6462132

我假设您希望获得流中最常见的数字。因此,您可以使用树状图来收集所有结果并获取最后一个条目的列表:Map<Integer,&nbsp;Long>&nbsp;collect&nbsp;=&nbsp;Stream.of(1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;4,&nbsp;55555,&nbsp;12) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.groupingBy(Function.identity(),&nbsp;Collectors.counting())) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.entrySet().stream() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.groupingBy(Map.Entry::getValue,&nbsp;TreeMap::new,&nbsp;Collectors.toMap(Map.Entry::getKey,&nbsp;Map.Entry::getValue))) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.lastEntry().getValue();这将返回包含数字和频率的条目列表。在您的情况下,它打印:{4=2}如果您只想获得最大数字的出现次数,则可以使用以下命令:Map.Entry<Integer,&nbsp;Long>&nbsp;collect&nbsp;=&nbsp;Stream.of(1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;4,&nbsp;55555,&nbsp;12) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.groupingBy(Function.identity(),&nbsp;Collectors.counting())) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.entrySet().stream() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.max(Map.Entry.comparingByKey()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.orElse(null);哪些打印:55555=1在最后一种情况下,您只有一个(最大值)返回条目。也可以使用一个获取最大值,应该有更好的性能。TreeMap
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java