Come ottenere il massimo valore dalla raccolta (ad esempio ArrayList)?


134

Esiste un ArrayList che memorizza valori interi. Devo trovare il valore massimo in questo elenco. Ad esempio supponiamo che i valori memorizzati arrayList siano: 10, 20, 30, 40, 50e il valore massimo sarebbe 50.

Qual è il modo efficiente per trovare il valore massimo?

@Edit: ho appena trovato una soluzione per la quale non sono molto sicuro

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

Integer i = Collections.max(arrayList)

e questo restituisce il valore più alto.

Un altro modo per confrontare ciascun valore, ad es selection sort or binary sort algorithm  


2
Hai provato a trovare il valore? Dove ti sei bloccato? La tua soluzione è forse troppo inefficiente?
— Anthony Pegram,

1
Se è qualcosa che fai molto Java lo compilerà in assembly, quindi a meno che tu non faccia qualcosa di stupido, il tuo codice sarà abbastanza efficiente con un semplice iteratore.
— Bill K,

@AnthonyPegram: intendo quale algoritmo di ordinamento o esiste un metodo in Java? A proposito, controlla la risposta dei gotomanners.
— user1010399


Risposte:


292

È possibile utilizzare il Collections APIper ottenere ciò che si desidera facilmente - leggere in modo efficiente - Javadoc sufficiente per Collections.max

Collections.max(arrayList);

Restituisce l'elemento massimo della raccolta data, in base all'ordinamento naturale dei suoi elementi. Tutti gli elementi della raccolta devono implementare l'interfaccia Comparable.


8
Perché questa è la risposta accettata? E ' non è la soluzione più efficiente. Nel migliore dei casi, è O (n log (n)) e scegliere il massimo controllandoli tutti è solo O (n)
— Brendan Long

Sì, è possibile scorrere l'elenco O(n log(n))ma se "Non esiste un modo particolarmente efficiente", cosa proponi che sia una soluzione migliore oltre a controllarli tutti?
— gotomanners

L'iterazione ingenua è più veloce (selezionato, il comparatore stava recuperando i punteggi da una mappa) rispetto all'ordinamento e al primo elemento o all'utilizzo di max. Sia sort + take first che max hanno usato un lambda.
— majTheHero

31

Questa domanda ha quasi un anno, ma ho scoperto che se si crea un comparatore personalizzato per gli oggetti, è possibile utilizzare Collections.max per un elenco di array di oggetti.

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

hai bisogno di un comparatore personalizzato per i tipi di calendario?
— tatmanblue,

Il codice restituisce il valore più piccolo nell'elenco, se (a.getPopulation ()> b.getPopulation ()) restituisce -1; Quanto sopra deve cambiare in, se (a.getPopulation () <b.getPopulation ()) restituisce -1; // prima il valore più alto
— Chandrakanth Gowda

Questo può essere fatto anche usando un lambda: 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;
}

Da quanto ho capito, questo è fondamentalmente ciò che fa Collections.max (), sebbene utilizzino un comparatore poiché gli elenchi sono generici.


Questo è più veloce di ogni altra cosa per il mio caso.
— majTheHero

14

Possiamo semplicemente usare Collections.max()e Collections.min()metodo.

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

8

La classe Integer implementa Comparable.Quindi possiamo facilmente ottenere il valore massimo o minimo dell'elenco Integer.

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

Se una classe non implementa Comparable e dobbiamo trovare il valore massimo e minimo, allora dobbiamo scrivere il nostro comparatore.

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

In Java 8, le raccolte sono state migliorate utilizzando lambda. Quindi la ricerca di max e min può essere eseguita come segue, usando Comparator.comparing:

Codice:

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

Produzione:

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

5

Non esiste un modo particolarmente efficace per trovare il valore massimo in un elenco non ordinato: è sufficiente controllarli tutti e restituire il valore più alto.


che dire di questo numero intero i = Collections.max(arrayList). restituisce il valore più alto nel mio caso se non ne sono molto sicuro. cosa dici?
— user1010399

@ user1010399 - Fa esattamente quello che sto dicendo - Controlla ogni valore e restituisce quello più alto.
— Brendan Long,

ok va bene. Grazie. ero un po 'confuso tra questo metodo di raccolta e l'algoritmo di ordinamento.
— user1010399

4

Ecco altri tre modi per trovare il valore massimo in un elenco, usando gli stream:

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

Tutti questi metodi, proprio come Collections.max, ripetono l'intera collezione, quindi richiedono un tempo proporzionale alla dimensione della collezione.


3

Java 8

Poiché i numeri interi sono comparabili, possiamo usare la seguente riga in:

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

Un altro punto da notare è che non possiamo usare Funtion.identity()al posto di i->icome ci si mapToIntaspetta, ToIntFunctionche è un'interfaccia completamente diversa e non correlata Function. Inoltre questa interfaccia ha un solo metodo applyAsInte nessun identity()metodo.


1

Ecco la fucntion

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

Oltre alla risposta di gotomanners , nel caso in cui qualcun altro venisse qui alla ricerca di una soluzione nulla sicura allo stesso problema, questo è quello che ho finito

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


0
model =list.stream().max(Comparator.comparing(Model::yourSortList)).get();

-3

a seconda delle dimensioni dell'array, una soluzione multithread potrebbe anche velocizzare le cose


Sembra più un commento che una risposta reale alla domanda.
— Pac0,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.