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.