如何在 Java 的列表中找到所有最大值?

How to find ALL maximum values in a List in Java?

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

我想将这 2 个元素打印到控制台 - 作为数组中的最大数字,但是 Collections.max () 方法 returns 只有它找到的第一个最大值,即,只有索引 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() 来查找所有最大值?

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

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

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

    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}

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 使用它的默认比较器,它对所有基元、盒装基元和字符串都有。对单词和数字进行排序是众所周知的自然事情,不需要任何实现。

您可以先找到 maximal elements by lifting 整数值到列表中,然后减少该列表:

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