Pregunta ¿Cómo puedo probar si una matriz contiene un cierto valor?


tengo un String[] con valores como ese:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

Dado String s, hay una buena manera de probar si VALUES contiene s?


1850
2017-07-15 00:03


origen


Respuestas:


Arrays.asList(yourArray).contains(yourValue)

Advertencia: esto no funciona para arreglos de primitivos (ver los comentarios).


Ya que

Ahora puede usar un Stream para comprobar si una serie de int, double o long contiene un valor (usando respectivamente una IntStream, DoubleStream o LongStream)

Ejemplo

int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);

2423
2017-07-15 00:04



Solo para borrar el código para empezar. Tenemos (corregido):

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

Esta es una estática mutable que FindBugs te dirá que es muy travieso. Debe ser privado:

private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

(Tenga en cuenta que en realidad puede soltar el new String[]; poco.)

Entonces, las matrices de referencia son malas, y en particular aquí queremos un conjunto:

private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
     new String[] {"AB","BC","CD","AE"}
));

(Las personas paranoides, como yo, pueden sentirse más a gusto si esto estuviera envuelto en Collections.unmodifiableSet - incluso podría hacerse público.)

"Given String s, ¿hay una buena forma de probar si VALUES contiene s?"

VALUES.contains(s)

O (1).


309
2017-07-15 01:13



Puedes usar ArrayUtils.contains de Apache Commons Lang

public static boolean contains(Object[] array, Object objectToFind)

Tenga en cuenta que este método regresa false si el conjunto pasado es null.

También hay métodos disponibles para matrices primitivas de todo tipo.

Ejemplo:

String[] fieldsToInclude = { "id", "name", "location" };

if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
    // Do some stuff.
}

171
2018-05-31 13:17



Me sorprende que nadie sugiriera simplemente implementarlo a mano:

public static <T> boolean contains(final T[] array, final T v) {
    for (final T e : array)
        if (e == v || v != null && v.equals(e))
            return true;

    return false;
}

Mejora:

los v != null la condición es constante dentro del método, siempre se evalúa con el mismo valor booleano durante la llamada al método. Entonces si la entrada array es grande, es más eficiente evaluar esta condición solo una vez y podemos usar una condición simplificada / más rápida dentro del for lazo basado en el resultado. La mejora contains() método:

public static <T> boolean contains2(final T[] array, final T v) {
    if (v == null) {
        for (final T e : array)
            if (e == null)
                return true;
    } else {
        for (final T e : array)
            if (e == v || v.equals(e))
                return true;
    }

    return false;
}

142
2017-09-28 07:45



Si la matriz no está ordenada, tendrá que iterar sobre todo y hacer una llamada a iguales en cada una.

Si la matriz está ordenada, puede hacer una búsqueda binaria, hay una en el Arrays clase.

En términos generales, si va a hacer muchas comprobaciones de membresía, es posible que desee almacenar todo en un conjunto, no en un conjunto.


65
2017-07-15 00:05



Cuatro formas diferentes de verificar si una matriz contiene un valor

1) Usando la lista:

public static boolean useList(String[] arr, String targetValue) {
    return Arrays.asList(arr).contains(targetValue);
}

2) Usando Set:

public static boolean useSet(String[] arr, String targetValue) {
    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);
}

3) Usando un bucle simple:

public static boolean useLoop(String[] arr, String targetValue) {
    for (String s: arr) {
        if (s.equals(targetValue))
            return true;
    }
    return false;
}

4) Usando Arrays.binarySearch ():

El código siguiente es incorrecto, se detalla aquí para completarlo. binarySearch () SOLAMENTE se puede usar en arreglos ordenados. Encontrará que el resultado es extraño a continuación. Esta es la mejor opción cuando se ordena el conjunto.

public static boolean binarySearch(String[] arr, String targetValue) {  
            int a = Arrays.binarySearch(arr, targetValue);
            return a > 0;
        }

Ejemplo rápido:

String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false

59
2018-05-07 19:14



Por lo que vale, realicé una prueba comparando las 3 sugerencias de velocidad. Genere enteros aleatorios, los convertí en una cadena y los agregué a una matriz. Luego busqué el mayor número / cadena posible, que sería el peor de los casos para el asList (). Contains ().

Cuando se usa un tamaño de matriz de 10K, los resultados son:

Ordenar y Buscar: 15
Búsqueda binaria: 0
asList.contains: 0

Cuando se usa una matriz de 100 K los resultados son:

Ordenar y Buscar: 156
Búsqueda binaria: 0
asList.contains: 32

Entonces, si la matriz se crea en orden ordenado, la búsqueda binaria es la más rápida, de lo contrario, el asList (). Contiene sería el camino a seguir. Si tiene muchas búsquedas, puede valer la pena ordenar la matriz para que pueda usar la búsqueda binaria. Todo depende de tu aplicación.

Creo que esos son los resultados que la mayoría de la gente esperaría. Aquí está el código de prueba:

import java.util.*;

public class Test
{
    public static void main(String args[])
    {
        long start = 0;
        int size = 100000;
        String[] strings = new String[size];
        Random random = new Random();


        for (int i = 0; i < size; i++)
            strings[i] = "" + random.nextInt( size );

        start = System.currentTimeMillis();
        Arrays.sort(strings);
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1) ));
        System.out.println("Sort & Search : " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1) ));
        System.out.println("Search        : " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.asList(strings).contains( "" + (size - 1) ));
        System.out.println("Contains      : " + (System.currentTimeMillis() - start));
    }
}

46
2017-07-15 01:28



En lugar de utilizar la sintaxis de inicialización de matriz rápida, puede inicializarla como una lista de forma similar utilizando el método Arrays.asList, p. Ej .:

public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");

Entonces puedes hacer (como arriba): STRINGS.contains("the string you want to find");


29
2018-01-20 13:58



Con Java 8 puedes crear una transmisión y verificar si alguna entrada en la secuencia coincide "s":

String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);

O como un método genérico:

public static <T> boolean arrayContains(T[] array, T value) {
    return Arrays.stream(array).anyMatch(value::equals);
}

29
2018-03-13 14:53