Domanda Come posso verificare se un array contiene un certo valore?


Ho un String[] con valori come questi:

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

Dato String s, c'è un buon modo per testare se VALUES contiene s?


1848
2017-07-15 00:03


origine


risposte:


Arrays.asList(yourArray).contains(yourValue)

Attenzione: questo non funziona per gli array di primitivi (vedere i commenti).


Da

Ora puoi usare a Stream per verificare se un array di int, double o long contiene un valore (utilizzando rispettivamente a IntStream, DoubleStream o LongStream)

Esempio

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

2421
2017-07-15 00:04



Solo per cancellare il codice fino all'inizio. Abbiamo (corretto):

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

Questa è una statica mutabile che FindBugs ti dirà è molto cattiva. Dovrebbe essere privato:

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

(Nota, puoi effettivamente abbandonare il new String[]; po.)

Quindi, gli array di riferimento sono cattivi, e in particolare qui vogliamo un set:

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

(Le persone paranoiche, come me, potrebbero sentirsi più a loro agio se questo fosse avvolto Collections.unmodifiableSet - potrebbe anche essere reso pubblico.)

"Dato String s, c'è un buon modo per testare se VALUE contiene s?"

VALUES.contains(s)

O (1).


309
2017-07-15 01:13



Puoi usare ArrayUtils.contains a partire dal Apache Commons Lang

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

Si noti che questo metodo restituisce false se l'array passato è null.

Esistono anche metodi disponibili per gli array primitivi di tutti i tipi.

Esempio:

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

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

171
2018-05-31 13:17



Sono sorpreso che nessuno abbia suggerito semplicemente di 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;
}

Miglioramento:

Il v != null la condizione è costante all'interno del metodo, sempre valuta lo stesso valore booleano durante la chiamata al metodo. Quindi se l'input array è grande, è più efficiente valutare questa condizione solo una volta e possiamo usare una condizione semplificata / più veloce all'interno di for loop basato sul risultato. Il miglioramento contains() metodo:

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



Se la matrice non è ordinata, dovrai eseguire iterazioni su tutto e fare una chiamata a uguale su ciascuna.

Se la matrice è ordinata, puoi fare una ricerca binaria, ce n'è una nella Array classe.

In generale, se si stanno facendo molti controlli sull'effettivo, è possibile memorizzare tutto in un Set, non in un array.


65
2017-07-15 00:05



Quattro diversi modi per verificare se una matrice contiene un valore

1) Uso dell'elenco:

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

2) Utilizzo del set:

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

3) Utilizzando un semplice ciclo:

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

4) Utilizzo di Arrays.binarySearch ():

Il codice qui sotto è sbagliato, è elencato qui per completezza. binarySearch () può essere usato SOLO su array ordinati. Troverete che il risultato è strano di seguito. Questa è l'opzione migliore quando l'array è ordinato.

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

Esempio veloce:

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



Per quello che vale ho eseguito un test confrontando i 3 suggerimenti per la velocità. Ho generato numeri casuali interi, li ho convertiti in una stringa e li ho aggiunti a una matrice. Ho quindi cercato il numero / stringa più alto possibile, che sarebbe uno scenario peggiore per asList (). Contains ().

Quando si utilizza una dimensione dell'array 10K, i risultati dove:

Ordina e cerca: 15
Ricerca binaria: 0
asList.contains: 0

Quando si utilizza un array 100K, i risultati dove:

Ordina e cerca: 156
Ricerca binaria: 0
asList.contains: 32

Quindi se la matrice viene creata in ordine ordinato, la ricerca binaria è la più veloce, altrimenti la lista asList (). Contiene sarebbe la strada da percorrere. Se hai molte ricerche, potrebbe essere utile ordinare la matrice in modo da poter usare la ricerca binaria. Tutto dipende dalla tua applicazione.

Penserei che quelli sono i risultati che la maggior parte della gente si aspetterebbe. Ecco il codice di prova:

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



Invece di utilizzare la sintassi di inizializzazione dell'array veloce, è possibile inizializzarlo come elenco direttamente in un modo simile utilizzando il metodo Arrays.asList ad esempio:

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

Quindi puoi fare (come sopra): STRINGS.contains("the string you want to find");


29
2018-01-20 13:58



Con Java 8 è possibile creare uno stream e verificare se le voci nello stream corrispondono "s":

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

O come metodo generico:

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

29
2018-03-13 14:53



Puoi usare il Classe Array per eseguire una ricerca binaria per il valore. Se la matrice non è ordinata, sarà necessario utilizzare le funzioni di ordinamento nella stessa classe per ordinare la matrice, quindi cercare attraverso di essa.


22
2017-07-15 00:05



ObStupidAnswer (ma penso che ci sia una lezione qui da qualche parte):

enum Values {
    AB, BC, CD, AE
}

try {
    Values.valueOf(s);
    return true;
} catch (IllegalArgumentException exc) {
    return false;
}

15
2017-07-15 01:18