Encontrar el valor máximo / mínimo en una matriz de primitivas usando Java

186

Es trivial escribir una función para determinar el valor mínimo / máximo en una matriz, como:

/**
 * 
 * @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;
}

pero ¿no está esto ya hecho en alguna parte?

Nick Heiner
fuente
8
Una matriz de primitiva a una matriz de contenedores ayudaría: stackoverflow.com/questions/3770289/… seguido de Collections.max(Arrays.asList()).
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Me encanta lo tonto que es Java
Farid

Respuestas:

173

Usando Commons Lang (para convertir) + Colecciones (a 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));
   }
}

Tenga en cuenta que Arrays.asList()envuelve la matriz subyacente, por lo que no debe consumir demasiada memoria y no debe realizar una copia en los elementos de la matriz.

Michael Rutherfurd
fuente
9
qué esArrayUtils
Basheer AL-MOMANI
44
Arrays.asList()debería estar bien, pero ArrayUtils.toObject()copiará cada elemento de aa una nueva matriz de Character.
EM
55
Arrays.asList(a)no funciona No puede hacer una lista de primitivas ( List<char>en este caso). Primero necesita convertir los valores primitivos en objetos y por eso ArrayUtils.toObjectse usa.
nessa.gp
96

Simplemente puede usar los nuevos Java 8 Streams pero tiene que trabajar con ellos int.

El streammétodo de la clase de utilidad Arraysle proporciona un método para IntStreamusar el minmétodo. También se puede hacer max, sum, average, ...

El getAsIntmétodo se utiliza para obtener el valor deOptionalInt

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

}

== ACTUALIZACIÓN ==

Si el tiempo de ejecución es importante y desea revisar los datos solo una vez, puede usar el summaryStatistics()método de esta manera

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

Este enfoque puede proporcionar un mejor rendimiento que el bucle clásico porque el summaryStatisticsmétodo es una operación de reducción y permite la paralelización.

Ortomala Lokni
fuente
57

La biblioteca Google Guava tiene métodos min y max en sus clases Chars, Ints, Longs, etc.

Entonces simplemente puedes usar:

Chars.min(myarray)

No se requieren conversiones y presumiblemente se implementa de manera eficiente.

Andrew McKinlay
fuente
44
Se implementa más o menos como en la pregunta, excepto que arroja una IllegalArgumentException para una matriz de longitud 0. ( code.google.com/p/guava-libraries/source/browse/trunk/src/com/… )
ColinD
3
Esta es la mejor solución de todo aquí. Evita toda esa confusión java.util.Arrays # asList varargs.
Kong
20

Sí, se hace en la clase Colecciones . Tenga en cuenta que deberá convertir su primitiva matriz de caracteres a un carácter [] manualmente.

Una breve demostración:

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)));
    }
}
Bart Kiers
fuente
1
Collections.min (myCollection); Si desea usarlo para matrices, puede hacerlo como Collections.min (Arrays.asList (myArray));
Zed
3
convertir a char []a Character []solo para determinar el máximo es bastante ineficiente; mejor cree una clase de utilidad con métodos estáticos para cada tipo primitivo similar a java.util.Arrays: java.sun.com/javase/6/docs/api/java/util/Arrays.html
Christoph
@ Christoph: sí, si el tamaño de la matriz es grande, estaría de acuerdo. Simplemente decir que es "ineficiente" no tiene sentido si la aplicación en cuestión realiza muchas llamadas a la base de datos y / u operaciones de E / S y el tamaño de la matriz es (relativo) pequeño.
Bart Kiers
debe usar en Character.valueOf(chars[i])lugar de new Character(chars[i])por razones de rendimiento: java.sun.com/javase/6/docs/api/java/lang/…
Christoph
@ Christoph Christoph tiene razón, es ineficiente y estúpido transformar una matriz en una Colección, para una búsqueda mínima máxima.
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);

  }

}
Lubna_Nsour
fuente
44
Por favor proporcione alguna explicación.
Mike Stockdale
3
Creo que lo que esto significa decir es que si ordena la matriz (en orden ascendente), por definición, el valor mínimo siempre estará en la primera posición, a [0], y el valor máximo siempre estará en la última posición , [a.length-1].
Jeff
1
Esta es una forma legítima y útil de resolver el problema. ¿Cuál es la desventaja de usarlo en comparación con los otros?
Alex
8
@alex complejidad de tiempo: la clasificación es, en el mejor de los casos, un asunto de O (nlogn), mientras que el enfoque de Michael Rutherfurd es O (n).
jajdoo
3
No necesitamos ordenar, ya que una sola iteración sobre la lista es suficiente para encontrar min y max.
akhil_mittal
11

Tengo una pequeña clase auxiliar en todas mis aplicaciones con métodos como:

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

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

    return max;
}
Sauer
fuente
1
Debe usar double max = Double.NEGATIVE_INFINITY; en lugar de double max = Double.MIN_VALUE; Como MIN_VALUE para doble es positivo
krems
1
... o puede establecer max en el primer elemento de la matriz e iterar desde el segundo elemento, vea mi respuesta.
Nicholas Hamilton
3

Podrías hacerlo fácilmente con un IntStreamy el max()método.

Ejemplo

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

Explicación

  1. range(0, intArray.length)- Para obtener una secuencia con tantos elementos como presente en el intArray.

  2. map(i -> intArray[i])- Asigna cada elemento de la secuencia a un elemento real de la intArray.

  3. max()- Obtenga el elemento máximo de esta secuencia como OptionalInt.

  4. getAsInt()- Desenvuelve el OptionalInt. (También puede usar aquí: orElse(0)en caso de que OptionalIntesté vacío).

winklerrr
fuente
2

Aquí hay una clase de utilidad que proporciona min/maxmétodos para tipos primitivos: Primitives.java

Christoph
fuente
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);
}
}
Marca 2
fuente
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;
    }
Nicholas Hamilton
fuente
Esto es para números, intpero la pregunta es pedir valores primitivosint, long, char, byte....
IgniteCoders
2

Una solución 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

En el código anterior, reduce()devuelve datos en Optionalformato, que puede convertir intporgetAsInt() .

Si queremos comparar el valor máximo con un cierto número, podemos establecer un valor inicial en 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

En el código anterior, cuando reduce()tiene una identidad (valor de inicio) como primer parámetro, devuelve datos en el mismo formato que la identidad. Con esta propiedad, podemos aplicar esta solución a otras matrices:

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
Simon Z.
fuente
1

Ejemplo con flotador:

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];
}
Andrey
fuente
Si bien su solución funcionará, aumentará la complejidad del tiempo a O (nlogn), mientras que min se puede encontrar fácilmente en O (n) mediante el uso de otras respuestas.
Pramod
simplemente loco usar una especie en esta situación.
Nicholas Hamilton
Puede ser útil cuando se necesita el primer n> 1 valor más pequeño / más grande, con algunas reparaciones.
biziclop
1

Aquí hay una solución para obtener el valor máximo en aproximadamente el 99% de las ejecuciones (cambie el 0.01 para obtener un mejor resultado):

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

(No completamente serio)

mnzl
fuente
;-) Eso es "No del todo serio" bien. Dudando a votar ...
Ole VV
0

Pase la matriz a un método que la clasifique Arrays.sort()para que solo clasifique la matriz que está utilizando el método y luego establezca min to array[0]y max to array[array.length-1].

quien espera
fuente
3
Probablemente valga la pena señalar que a) esto modifica la matriz yb) para matrices grandes es una solución más costosa O (nlog n) en lugar de O (n)
davidsheldon
0

La forma básica de obtener el valor mínimo / máximo de una matriz. Si necesita la matriz sin clasificar, puede crear una copia o pasarla a un método que devuelva el mínimo o el máximo. Si no, la matriz ordenada es mejor ya que en algunos casos funciona más rápido.

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);
    }
}
Kim G.
fuente
2
El problema con la clasificación es que tiene una sobrecarga de O (n log n) para un problema de O (n). Pero esto es mejor que las otras tres respuestas de "ordenar la matriz" ya dadas.
Teepeemm