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.