Trovare il valore massimo / minimo in una matrice di primitive usando Java


186

È banale scrivere una funzione per determinare il valore min / max in un array, come:

/**
 * 
 * @param chars
 * @return the max value in the array of chars
 */
private static int maxValue(char[] chars) {
    int max = chars[0];
    for (int ktr = 0; ktr < chars.length; ktr++) {
        if (chars[ktr] > max) {
            max = chars[ktr];
        }
    }
    return max;
}

ma non è già stato fatto da qualche parte?


8
Un array di primitive a un array di contenitori sarebbe di aiuto: stackoverflow.com/questions/3770289/… seguito da Collections.max(Arrays.asList()).
Ciro Santilli 13 冠状 病 六四 事件 法轮功

Adoro quanto sia stupido Java
Farid,

Risposte:


173

Uso di Commons Lang (per convertire) + Collezioni (in min / max)

import java.util.Arrays;
import java.util.Collections;

import org.apache.commons.lang.ArrayUtils;

public class MinMaxValue {

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};

        List b = Arrays.asList(ArrayUtils.toObject(a));

        System.out.println(Collections.min(b));
        System.out.println(Collections.max(b));
   }
}

Si noti che Arrays.asList()avvolge l'array sottostante, quindi non dovrebbe richiedere troppo memoria e non deve eseguire una copia sugli elementi dell'array.


9
cos'èArrayUtils
Basheer AL-MOMANI

4
Arrays.asList()dovrebbe andare bene, ma ArrayUtils.toObject()copierà ogni elemento ain un nuovo array di Character.
EM,

5
Arrays.asList(a)non funziona Non è possibile creare un elenco di primitivi ( List<char>in questo caso). Per prima cosa devi convertire i valori primitivi in ​​oggetti ed è per questo che ArrayUtils.toObjectviene utilizzato.
nessa.gp,

96

Si può semplicemente utilizzare le nuove Java 8 Streams , ma si deve lavorare con int.

Il streammetodo della classe di utilità Arraysfornisce un metodo IntStreamsu cui è possibile utilizzare il minmetodo. Si può anche fare max, sum, average, ...

Il getAsIntmetodo viene utilizzato per ottenere il valore daOptionalInt

import java.util.Arrays;

public class Test {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        int min = Arrays.stream(tab).min().getAsInt();
        int max = Arrays.stream(tab).max().getAsInt();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max)
    }

}

== AGGIORNAMENTO ==

Se il tempo di esecuzione è importante e si desidera esaminare i dati solo una volta, è possibile utilizzare il summaryStatistics()metodo in questo modo

import java.util.Arrays;
import java.util.IntSummaryStatistics;

public class SOTest {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
        int min = stat.getMin();
        int max = stat.getMax();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max);
    }
}

Questo approccio può fornire prestazioni migliori rispetto al loop classico perché il summaryStatisticsmetodo è un'operazione di riduzione e consente la parallelizzazione.


57

La libreria di Google Guava ha metodi min e max nelle sue classi Chars, Ints, Longs, ecc.

Quindi puoi semplicemente usare:

Chars.min(myarray)

Non sono necessarie conversioni e presumibilmente è implementato in modo efficiente.


4
È implementato più o meno come nella domanda tranne per il fatto che genera un'eccezione IllegalArgumentException per un array di lunghezza 0. ( code.google.com/p/guava-libraries/source/browse/trunk/src/com/… )
ColinD

3
Questa è la migliore soluzione di tutto qui. Evita tutta quella confusione di java.util.Arrays # asList varargs.
Kong,

20

Sì, è fatto nella classe Collezioni . Nota che dovrai convertire manualmente il tuo array di caratteri primitivo in un carattere [].

Una breve demo:

import java.util.*;

public class Main {

    public static Character[] convert(char[] chars) {
        Character[] copy = new Character[chars.length];
        for(int i = 0; i < copy.length; i++) {
            copy[i] = Character.valueOf(chars[i]);
        }
        return copy;
    }

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};
        Character[] b = convert(a);
        System.out.println(Collections.max(Arrays.asList(b)));
    }
}

1
Collections.min (myCollection); Se vuoi usarlo per le matrici, puoi farlo come Collections.min (Arrays.asList (myArray));
Zed,

3
la conversione di a char []in Character []solo per determinare il massimo è abbastanza inefficiente - è meglio creare una classe di utilità con metodi statici per ogni tipo di primitiva simile a java.util.Arrays: java.sun.com/javase/6/docs/api/java/util/Arrays.html
Christoph,

@Christoph: sì, se la dimensione dell'array è grande, sono d'accordo. La semplice affermazione che è "inefficiente" non ha senso se l'applicazione in questione effettua molte chiamate al database e / o operazioni di I / O e la dimensione dell'array è (relativa) ridotta.
Bart Kiers,

dovresti usare Character.valueOf(chars[i])invece new Character(chars[i])per motivi di performance: java.sun.com/javase/6/docs/api/java/lang/…
Christoph,

@Christoph Christoph ha ragione, è inefficiente e stupido trasformare un array in una Collection, per una ricerca minima.
AlexWien,

16
import java.util.Arrays;

public class apples {

  public static void main(String[] args) {
    int a[] = {2,5,3,7,8};
    Arrays.sort(a);

     int min =a[0];
    System.out.println(min);
    int max= a[a.length-1];
    System.out.println(max);

  }

}

4
Si prega di fornire alcune spiegazioni.
Mike Stockdale,

3
Penso che questo significhi che se si ordina l'array (in ordine crescente), per definizione, il valore minimo sarà sempre nella prima posizione, uno [0] e il valore massimo sarà sempre nell'ultima posizione , [a.length-1].
Jeff,

1
Questo è un modo legittimo e utile per risolvere il problema. Qual è lo svantaggio di usarlo rispetto agli altri?
Alex,

8
@alex complessità temporale - l'ordinamento è nella migliore delle ipotesi un affare O (nlogn), mentre l'approccio di Michael Rutherfurd è O (n).
Jajdoo,

3
Non è necessario ordinare poiché è sufficiente una singola iterazione sull'elenco per trovare min e max.
akhil_mittal

11

Ho una piccola classe di supporto in tutte le mie applicazioni con metodi come:

public static double arrayMax(double[] arr) {
    double max = Double.NEGATIVE_INFINITY;

    for(double cur: arr)
        max = Math.max(max, cur);

    return max;
}

1
Dovresti usare double max = Double.NEGATIVE_INFINITY; anziché doppio max = Double.MIN_VALUE; Dato che MIN_VALUE per il doppio è positivo
krems il

1
... oppure potresti impostare max al primo elemento dell'array e iterare dal secondo elemento, vedi la mia risposta.
Nicholas Hamilton,

3

Si potrebbe facilmente farlo con un IntStreame il max()metodo.

Esempio

public static int maxValue(final int[] intArray) {
  return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}

Spiegazione

  1. range(0, intArray.length)- Per ottenere un flusso con tutti gli elementi presenti nel file intArray.

  2. map(i -> intArray[i])- Mappa ogni elemento del flusso su un elemento reale di intArray.

  3. max()- Ottieni il massimo elemento di questo flusso come OptionalInt.

  4. getAsInt()- Scartare il OptionalInt. (Puoi anche usare qui orElse(0):, nel caso in cui OptionalIntsia vuoto.)



2
import java.util.Random;

public class Main {

public static void main(String[] args) {
   int a[] = new int [100];
   Random rnd = new Random ();

    for (int i = 0; i< a.length; i++) {
        a[i] = rnd.nextInt(99-0)+0;
        System.out.println(a[i]);
    }

    int max = 0;          

    for (int i = 0; i < a.length; i++) {
        a[i] = max;


        for (int j = i+1; j<a.length; j++) {
            if (a[j] > max) {
               max = a[j];
            }

        }
    }

    System.out.println("Max element: " + max);
}
}

2
    public int getMin(int[] values){
        int ret = values[0];
        for(int i = 1; i < values.length; i++)
            ret = Math.min(ret,values[i]);
        return ret;
    }

Questo è per i numeri intma la domanda è chiedere valori primitiviint, long, char, byte....
IgniteCoders

2

Una soluzione con reduce() :

int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);

// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97

Nel codice sopra, reduce()restituisce i dati inOptional formato, che è possibile convertire in intda getAsInt().

Se vogliamo confrontare il valore massimo con un certo numero, possiamo impostare un valore iniziale in reduce() :

int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100

Nel codice sopra, quando reduce()con un'identità (valore iniziale) come primo parametro, restituisce i dati nello stesso formato con l'identità. Con questa proprietà, possiamo applicare questa soluzione ad altri array:

double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0

1

Esempio con float:

public static float getMaxFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[data.length - 1];
}

public static float getMinFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[0];
}

Mentre la tua soluzione funzionerà, ma aumenterà la complessità temporale a O (nlogn) mentre min può essere trovato facilmente in O (n) usando altre risposte.
Pramod,

semplicemente pazzo per usare una specie in questa situazione.
Nicholas Hamilton,

Può essere utile quando è necessario il primo n> 1 valore più piccolo / più grande, con alcune riparazioni.
biziclop,

1

Ecco una soluzione per ottenere il valore massimo in circa il 99% delle esecuzioni (modificare lo 0,01 per ottenere un risultato migliore):

public static double getMax(double[] vals){
    final double[] max = {Double.NEGATIVE_INFINITY};

    IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
            .forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);

    return max[0];
}

(Non del tutto serio)


;-) Va bene "Non del tutto serio". Esitando a votare ...
Ole VV,

0

Passare la matrice a un metodo che sorta IT con Arrays.sort()in modo che ordina solo la matrice il metodo utilizza quindi imposta min per array[0]e max a array[array.length-1].


3
Probabilmente vale la pena notare che a) questo modifica l'array eb) per array di grandi dimensioni è una soluzione più costosa O (nlog n) anziché O (n)
davidsheldon

0

Il modo di base per ottenere il valore min / max di un array. Se è necessaria la matrice non ordinata, è possibile creare una copia o passarla a un metodo che restituisce il valore minimo o massimo. In caso contrario, l'array ordinato è migliore poiché in alcuni casi offre prestazioni più elevate.

public class MinMaxValueOfArray {
    public static void main(String[] args) {
        int[] A = {2, 4, 3, 5, 5};
        Arrays.sort(A);
        int min = A[0];
        int max = A[A.length -1];
        System.out.println("Min Value = " + min);        
        System.out.println("Max Value = " + max);
    }
}

2
Il problema con l'ordinamento è che ha un overhead O (n log n) per un problema O (n). Ma questo è meglio delle altre tre risposte "ordina l'array" già fornite.
Teepeemm,
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.