Jak uzyskać maksymalną wartość z kolekcji (na przykład ArrayList)?


138

Istnieje ArrayList, która przechowuje wartości całkowite. Muszę znaleźć maksymalną wartość na tej liście. Załóżmy na przykład, że przechowywane wartości arrayList to: 10, 20, 30, 40, 50a maksymalna wartość to 50.

Jaki jest skuteczny sposób na znalezienie maksymalnej wartości?

@Edit: Właśnie znalazłem jedno rozwiązanie, którego nie jestem pewien

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(100); /* add(200), add(250) add(350) add(150) add(450)*/

Integer i = Collections.max(arrayList)

a to zwraca najwyższą wartość.

Innym sposobem porównania każdej wartości, np selection sort or binary sort algorithm  


2
Czy próbowałeś znaleźć wartość? Gdzie utknęłaś? Twoje własne rozwiązanie może być zbyt nieefektywne?
— Anthony Pegram

1
Jeśli jest to coś, co robisz dużo, Java skompiluje to do asemblera, więc jeśli nie zrobisz czegoś głupiego, kod będzie całkiem wydajny dzięki prostemu iteratorowi.
— Bill K

@AnthonyPegram: mam na myśli, który algorytm sortowania lub czy jest jakaś metoda w java? A tak przy okazji, sprawdź odpowiedź gotomanners.
— user1010399


Odpowiedzi:


298

Możesz użyć Collections API, aby łatwo osiągnąć to, co chcesz - czytać wydajnie - wystarczającą ilość Javadoc dla Collections.max

Collections.max(arrayList);

Zwraca maksymalny element podanej kolekcji zgodnie z naturalnym uporządkowaniem jej elementów. Wszystkie elementy w kolekcji muszą implementować interfejs porównywalny.


10
Dlaczego jest to akceptowana odpowiedź? To nie jest najbardziej wydajne rozwiązanie. W najlepszym przypadku jest O (n log (n)), a wybranie maksimum poprzez sprawdzenie ich wszystkich to tylko O ​​(n)
— Brendan Long

1
Tak, iteracja listy jest O(n log(n))taka, ale jeśli „Nie ma szczególnie efektywnego sposobu”, to co proponujesz jako lepsze rozwiązanie oprócz sprawdzenia ich wszystkich?
— gotomanners

Naiwne iterowanie jest szybsze (zaznaczone, komparator pobierał wyniki z mapy) niż sortowanie i pobieranie pierwszego elementu lub używanie max. Zarówno sort + take first, jak i max używają lambdy.
— majTheHero

32

To pytanie ma już prawie rok, ale odkryłem, że jeśli tworzysz niestandardowy komparator dla obiektów, możesz użyć Collections.max jako tablicy tablicy obiektów.

import java.util.Comparator;

public class compPopulation implements Comparator<Country> {
    public int compare(Country a, Country b) {
        if (a.getPopulation() > b.getPopulation())
            return -1; // highest value first
        if (a.getPopulation() == b.Population())
            return 0;
        return 1;
    }
}
ArrayList<Country> X = new ArrayList<Country>();
// create some country objects and put in the list
Country ZZ = Collections.max(X, new compPopulation());

czy potrzebujesz niestandardowego komparatora dla typów kalendarza?
— tatmanblue

Twój kod zwraca najmniejszą wartość na liście, jeśli (a.getPopulation ()> b.getPopulation ()) return -1; Powyższe należy zmienić na, if (a.getPopulation () <b.getPopulation ()) return -1; // najpierw najwyższa wartość
— Chandrakanth Gowda

Można to również zrobić za pomocą lambdy: maxElement = Collections.max (collection, (el1, el2) -> el1 - el2);
— majTheHero

22
public int getMax(ArrayList list){
    int max = Integer.MIN_VALUE;
    for(int i=0; i<list.size(); i++){
        if(list.get(i) > max){
            max = list.get(i);
        }
    }
    return max;
}

Z mojego punktu widzenia jest to w zasadzie to, co robi Collections.max (), chociaż używają komparatora, ponieważ listy są ogólne.


W moim przypadku jest to szybsze niż cokolwiek innego.
— majTheHero

14

Możemy po prostu użyć Collections.max()i Collections.min()metody.

public class MaxList {
    public static void main(String[] args) {
        List l = new ArrayList();
        l.add(1);
        l.add(2);
        l.add(3);
        l.add(4);
        l.add(5);
        System.out.println(Collections.max(l)); // 5
        System.out.println(Collections.min(l)); // 1
    }
}

9

Klasa Integer implementuje Comparable, dzięki czemu możemy łatwo uzyskać maksymalną lub minimalną wartość listy Integer.

public int maxOfNumList() {
    List<Integer> numList = new ArrayList<>();
    numList.add(1);
    numList.add(10);
    return Collections.max(numList);
}

Jeśli klasa nie implementuje porównywalnego i musimy znaleźć wartość maksymalną i minimalną, musimy napisać własny komparator.

List<MyObject> objList = new ArrayList<MyObject>();
objList.add(object1);
objList.add(object2);
objList.add(object3);
MyObject maxObject = Collections.max(objList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        if (o1.getValue() == o2.getValue()) {
            return 0;
        } else if (o1.getValue() > o2.getValue()) {
            return -1;
        } else if (o1.getValue() < o2.getValue()) {
            return 1;
        }
        return 0;
    }
});

7

Comparator.comparing

W Javie 8 kolekcje zostały ulepszone przy użyciu lambda. Zatem znalezienie max i min można wykonać w następujący sposób, używając Comparator.comparing:

Kod:

List<Integer> ints = Stream.of(12, 72, 54, 83, 51).collect(Collectors.toList());
System.out.println("the list: ");
ints.forEach((i) -> {
    System.out.print(i + " ");
});
System.out.println("");
Integer minNumber = ints.stream()
        .min(Comparator.comparing(i -> i)).get();
Integer maxNumber = ints.stream()
        .max(Comparator.comparing(i -> i)).get();

System.out.println("Min number is " + minNumber);
System.out.println("Max number is " + maxNumber);

Wynik:

 the list: 12 72 54 83 51  
 Min number is 12 
 Max number is 83

5

Nie ma szczególnie wydajnego sposobu na znalezienie maksymalnej wartości na nieposortowanej liście - wystarczy sprawdzić je wszystkie i zwrócić najwyższą wartość.


co z tą liczbą całkowitą i = Collections.max(arrayList). zwraca najwyższą wartość w moim przypadku, czy nie jestem pewien. co mówisz?
— user1010399

@ user1010399 - Robi dokładnie to, o czym mówię - sprawdza każdą wartość i zwraca najwyższą.
— Brendan Long

ok, w porządku. dzięki. Byłem trochę zdezorientowany między tą metodą zbierania a algorytmem sortowania.
— user1010399

4

Oto trzy inne sposoby na znalezienie maksymalnej wartości na liście przy użyciu strumieni:

List<Integer> nums = Arrays.asList(-1, 2, 1, 7, 3);
Optional<Integer> max1 = nums.stream().reduce(Integer::max);
Optional<Integer> max2 = nums.stream().max(Comparator.naturalOrder());
OptionalInt max3 = nums.stream().mapToInt(p->p).max();
System.out.println("max1: " + max1.get() + ", max2: " 
   + max2.get() + ", max3: " + max3.getAsInt());

Wszystkie te metody, podobnie jak Collections.max, powtarzają się po całej kolekcji, dlatego wymagają czasu proporcjonalnego do wielkości kolekcji.


3

Java 8

Ponieważ liczby całkowite są porównywalne, możemy użyć następującego linera w:

List<Integer> ints = Stream.of(22,44,11,66,33,55).collect(Collectors.toList());
Integer max = ints.stream().mapToInt(i->i).max().orElseThrow(NoSuchElementException::new); //66
Integer min = ints.stream().mapToInt(i->i).min().orElseThrow(NoSuchElementException::new); //11

Kolejną kwestią, na którą należy zwrócić uwagę, jest to, że nie możemy używać Funtion.identity()zamiast tego, i->iczego mapToIntoczekuje, ToIntFunctionktóry jest zupełnie innym interfejsem i nie jest powiązany z Function. Ponadto ten interfejs ma tylko jedną metodę applyAsInti nie ma żadnej identity()metody.



1

Oto funkcja

public int getIndexOfMax(ArrayList<Integer> arr){
    int MaxVal = arr.get(0); // take first as MaxVal
    int indexOfMax = -1; //returns -1 if all elements are equal
    for (int i = 0; i < arr.size(); i++) {
        //if current is less then MaxVal
        if(arr.get(i) < MaxVal ){
            MaxVal = arr.get(i); // put it in MaxVal
            indexOfMax = i; // put index of current Max
        }
    }
    return indexOfMax;  
}

1
package in.co.largestinarraylist;

import java.util.ArrayList;
import java.util.Scanner;

public class LargestInArrayList {

    public static void main(String[] args) {

        int n;
        ArrayList<Integer> L = new ArrayList<Integer>();
        int max;
        Scanner in = new Scanner(System.in);
        System.out.println("Enter Size of Array List");
        n = in.nextInt();
        System.out.println("Enter elements in Array List");

        for (int i = 0; i < n; i++) {
            L.add(in.nextInt());
        }

        max = L.get(0);

        for (int i = 0; i < L.size(); i++) {
            if (L.get(i) > max) {
                max = L.get(i);
            }
        }

        System.out.println("Max Element: " + max);
        in.close();
    }
}

1

Oprócz odpowiedzi gotomanners , na wypadek, gdyby ktoś inny przyszedł tutaj, szukając zerowego bezpiecznego rozwiązania tego samego problemu, tak właśnie skończyłem

Collections.max(arrayList, Comparator.nullsFirst(Comparator.naturalOrder()))


-3

w zależności od rozmiaru tablicy rozwiązanie wielowątkowe może również przyspieszyć działanie


To brzmi bardziej jak komentarz niż rzeczywista odpowiedź na pytanie.
— Pac0
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.