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

I have a List that stores different numbers, the maximum of them are elements under indices: 2; 4.

I want to print these 2 elements to the console - as the maximum numbers in the array, but the Collections.max () method returns only the first maximum value it finds, that is, only the element at index 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

What should I use instead of method Collections.max() to find ALL maximum values?

5 answers

  • answered 2021-06-23 07:19 Roophie

    this uses one iteration to find them

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

  • answered 2021-06-23 07:25 LenglBoy

    There is no given function doing that by default. So what you can do is filtering this list for the given value. This will cause 2 iterations but be simple in code. If you do it in your own loop if it more code but more efficient.

    Depending on the amopunt of data you should choose efficient way or readable way.

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

  • answered 2021-06-23 07:28 Chengjun Guo

    You can first loop through the list to find the max value, and then loop the list again to put max valus and their index to a map.

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

    Output:

    {2=50, 4=50}

  • answered 2021-06-23 07:30 Nico Van Belle

    max will always find the maximum value and not the occurences. What you want will always have to be done in 2 steps.

    // 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() means that you do not provide a comparator but let Java use it's default comparator which it has for all primitives, boxed primitives and Strings. Sorting words and numbers is a natural thing that is well known and does not require any implementation.

  • answered 2021-06-23 09:58 michid

    You can find all maximal elements by lifting the integer values into a list first and reducing that list:

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