【问题标题】:How to find ALL maximum values in a List in Java?如何在Java列表中找到所有最大值?
【发布时间】:2021-09-06 17:28:46
【问题描述】:

我有一个存储不同数字的列表,它们中的最大值是索引下的元素:2; 4.

我想将这 2 个元素打印到控制台——作为数组中的最大数,但是 Collections.max() 方法只返回它找到的第一个最大值,即只返回索引 2 处的元素:

List<Integer> numbers = new ArrayList<Integer>();
        
        numbers.add(5);
        numbers.add(9);
        numbers.add(50);
        numbers.add(12);
        numbers.add(50);
        
        System.out.println(Collections.max(numbers));

|Output|
50

我应该使用什么代替方法 Collections.max() 来查找所有最大值?

【问题讨论】:

  • 先找到它,然后统计原始列表中出现的次数,然后多次打印找到的内容。
  • 每个怎么样,如果等于最大值,然后打印?
  • 不,它仍然输出一个值,而不是全部
  • @ArinaAznauryan 只有一个最大值,出现多次。

标签: java arrays list collections max


【解决方案1】:

这使用一次迭代来找到它们

List<Integer> numbers = new ArrayList<Integer>();
    numbers.add(5);
    numbers.add(9);
    numbers.add(50);
    numbers.add(12);
    numbers.add(50);
    int max = Integer.MIN_VALUE;
    int count = 1;
    for(int number : numbers){
        if(number > max){
            max = number;
            count = 1;
        } else if(number == max){
            count++;
        }
    }
    for(int i=0; i<count; i++){
        System.out.println(max);
    }

【讨论】:

    【解决方案2】:

    默认情况下没有给定的函数这样做。所以你可以做的是过滤这个列表以获得给定的值。这将导致 2 次迭代,但代码很简单。如果您在自己的循环中执行此操作,则代码更多但效率更高。

    根据数据的数量,你应该选择高效的方式或可读的方式。

    // 2 iterations - 1st for finding max , 2nd for filter
    int maxValue = Collections.max(numbers);
    List<Integer> maxValues = numbers.stream().filter(number -> number == max).collect(Collectors.toList()); // only need size? Add .size() at the end
    
    // efficient - just 1 iteration, but not pretty to read.
    int currentMax = numbers[0];
    int counter = 0;
    for(Integer number in numbers) {
        if(currentMax == number) {
            counter++;
        } else if(currentMax < number) {
            counter = 1;
            currentMax = number;
        }
    }
    

    【讨论】:

      【解决方案3】:

      max 总是会找到最大值而不是出现次数。你想要的总是必须分两步完成。

      // If you start from a List
      List<Integer> numbers = Arrays.asList(5, 9, 50, 12, 50);
      IntSummaryStatistics numberStats = numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));
      numbers.stream().filter(number -> number == numberStats.getMax()).forEach(System.out::println);
      
      // But you can also start from the stream itself
      IntSummaryStatistics numberStats = IntStream.of(5, 9, 50, 12, 50).summaryStatistics();
      numbers.stream().filter(number -> number == numberStats.getMax()).forEach(System.out::println);
      
      /*
       * You can also use the plain max number instead of the summaryStatistics, which is 
       * more performant but the stream cannot be reuse for e.g. min or average.
       * Note here we use equals because we don't use primitive int but Object Integer as it's not an IntSteam
       */
      Integer maxInt = numbers.stream().max(Comparator.naturalOrder()).orElseThrow();
      numbers.stream().filter(number -> number.equals(maxInt)).forEach(System.out::println);
      

      Comparator.naturalOrder() 表示您不提供比较器,而是让 Java 使用它的默认比较器,它对所有原语、盒装原语和字符串都有。对单词和数字进行排序是很自然的事情,众所周知,不需要任何实现。

      【讨论】:

        【解决方案4】:

        您可以先循环遍历列表以找到最大值,然后再次循环列表以将最大值及其索引放入地图。

            Map map = new HashMap();
            int curMax = 0;
            for (int i = 0; i < numbers.size(); i++) {
                if (numbers.get(i)>=curMax){
                    curMax = numbers.get(i);
                }
            }
            for (int i = 0; i < numbers.size(); i++) {
                if (numbers.get(i) == curMax){
                    map.put(i, numbers.get(i));
                }
            }
        
            System.out.println(map.toString());
        

        输出:

        {2=50, 4=50}

        【讨论】:

          【解决方案5】:

          您可以先通过lifting 找到maximal elements 的整数值到一个列表中并减少该列表:

              List<Integer> max = numbers.stream()
                  .collect(Collectors.reducing(
                      Collections.singletonList(Integer.MIN_VALUE),
                      Collections::singletonList,
                      (l1, l2) -> {
                          if (l1.get(0) > l2.get(0)) {
                              return l1;
                          } else if (l2.get(0) > l1.get(0)) {
                              return l2;
                          } else {
                              List<Integer> l = new ArrayList<>(l1);
                              l.addAll(l2);
                              return l;
                          }
                      }));
          

          【讨论】:

            猜你喜欢
            • 2011-04-28
            • 1970-01-01
            • 1970-01-01
            • 2019-12-09
            • 1970-01-01
            • 2017-01-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多