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

3

我有一个列表用于存储不同的数字,其中最大值分别在索引2和4下。

我想将这两个元素作为数组中的最大数打印到控制台上,但是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()方法以找到所有最大值?


首先找到它,然后计算原始列表中的出现次数,最后打印出你发现的内容相应的次数。 - Federico klez Culloca
对于每个元素,如果等于最大值,则打印输出怎么样? - Lei Yang
不,它仍然输出一个值,而不是全部。 - Arina Aznauryan
@ArinaAznauryan,只有一个最大值,但它出现了多次。 - Stultuske
5个回答

3

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

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

2

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使用默认的比较器,它适用于所有原始类型、包装类型和字符串。对单词和数字进行排序是一件自然而然的事情,这是众所周知的,不需要任何实现。


1
你可以先遍历列表以找到最大值,然后再遍历一次列表,将最大值和它们的索引放入一个映射中。
    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}


1

您可以通过将整数值提升到列表中并缩小该列表来找到最大元素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;
                }
            }));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接