代码之家  ›  专栏  ›  技术社区  ›  menteith

如何使用lambdas从列表及其出现的次数中找到最大的数字?

  •  0
  • menteith  · 技术社区  · 7 年前

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

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

    我如何将生成的地图限制为只有最大的数字(或者在平局的情况下是数字)?

    2 回复  |  直到 7 年前
        1
  •  0
  •   MS90    7 年前

    看看这个简单的例子:

    public static void getMeNumbersWithHighestFrequence3(int[] numbers, int howMany) {
    
        Map<Integer, Long> collect = IntStream.of(numbers).boxed().collect(groupingBy(Function.identity(), TreeMap::new, counting())).descendingMap().entrySet().stream()
                .limit(howMany)
                .collect(TreeMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), Map::putAll);
    
    }
    

    您也可以通过输入一个筛选值来搜索它们,它将获取键值大于该值的所有条目,如下所示:

      public static void getMeNumbersWithHighestFrequenceByFilterNumber(int[] numbers, int value) {
    
            Map<Integer, Long> collect = IntStream.of(numbers).boxed().collect(groupingBy(Function.identity(), TreeMap::new, counting())).descendingMap().headMap(value, true);
    
        }
    


    public static void main(String[] args) {
            int[] numbers = {1, 2, 3, 4, 4, 55555, 12};
            getMeNumbersWithHighestFrequence(numbers, 5);
        }
    
        2
  •  0
  •   Eugene    7 年前

    我希望有人能想出一个更简单的解决方案:

     List<Entry<Integer, Long>> list =
            List.of(3, 3, 4, 4, 5, 5, 1)
                .stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .entrySet()
                .stream()
                .sorted(Map.Entry.<Integer, Long>comparingByValue().reversed())
                .collect(Collectors.toList());
    
        Map<Integer, Long> result = new HashMap<>();
        Iterator<Entry<Integer, Long>> iter = list.iterator();
        Entry<Integer, Long> left;
        Entry<Integer, Long> right = null;
        while (iter.hasNext()) {
            left = iter.next();
            if (right == null) {
                result.put(left.getKey(), left.getValue());
            }
            if (iter.hasNext() && (right = iter.next()).getValue().longValue() == left.getValue()) {
                result.put(right.getKey(), right.getValue());
            } else {
                 break;
            }
        }
    

    所以首先把它们收集到你已经拥有的同一张地图上。然后按值对它们进行排序;然后迭代该结果并得到 只有

    其想法是,既然这些已经按值排序: 3 = 2; 4 = 2; 5 = 2; 1 = 1 -我们只需要重复这么长时间 2 != 2 只会变小)。

        3
  •  0
  •   Samuel Philipp    7 年前

    我想你想得到你流中最频繁的号码。因此,您可以使用 TreeMap 收集所有结果并获取最后一个条目的列表:

    Map<Integer, Long> collect = Stream.of(1, 2, 3, 4, 4, 55555, 12)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream()
            .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
            .lastEntry().getValue();
    

    {4=2}
    

    如果您只想获得最大数量的出现次数,可以使用以下方法:

    Map.Entry<Integer, Long> collect = Stream.of(1, 2, 3, 4, 4, 55555, 12)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream()
            .max(Map.Entry.comparingByKey())
            .orElse(null);
    

    哪个打印:

    55555=1
    

    在最后一种情况下,只有一个(最大值)返回项。也可以使用 树图

        4
  •  0
  •   user_3380739    7 年前

    我建议你用 MoreCollectors 定义于 StreamEx 或者我的图书馆 abacus-util

    int result = Stream.of(1, 2, 12, 3, 4, 4, 55555, 12)
        .collect(MoreCollectors.maxAll(MoreCollectors.countingInt()));
    
    // map result
    Map<Integer, Integer> mapResult = Stream.of(1, 2, 12, 3, 4, 4, 55555, 12)
        .collect(maxAll(groupingBy(Function.identity(), countingInt())));
    

    因为你可能想:1)所有最大的数字的总和,或2)映射到其他东西,或3)…更多。 不需要也不应该只为一个特定的用户案例编写这种特定的代码。(如果您想知道如何实现它,只需下载库的源代码或反编译类。它们发布在Apache许可证v2上)

    . 实际上,我认为如果你在谈论数字的话,问这个问题可能是错误的,因为传统的 for-loop 比使用lambdas简单高效:

    int[] 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) {
      if (num > result[0]) {
        result[0] = num;
        result[1] = 1;
      } else if (num == result[0]) {
        result[1]++;
      }
    }
    
    System.out.println(result[0] + ": " + result[1]);
    

    int[] result = IntStream.of(nums).collect(() -> new int[] {Integer.MIN_VALUE, 0}, (a, num) -> {
      if (num > a[0]) {
        a[0] = num;
        a[1] = 1;
      } else if (num == a[0]) {
        a[1]++;
      }
    }, (a1, a2) -> {
      if (a1[0] == a2[0]) {
        a1[1] += a2[1];
      } else if (a1[0] < a2[0]) {
        a1[1] = a2[1];
      }
    });
    
    System.out.println(result[0] + ": " + result[1]);
    
    推荐文章