Ho un String[]
valore con così:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dato String s
, c'è un buon modo per testare se VALUES
contiene s
?
Ho un String[]
valore con così:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dato String s
, c'è un buon modo per testare se VALUES
contiene s
?
Risposte:
Arrays.asList(yourArray).contains(yourValue)
Attenzione: questo non funziona con le matrici di primitivi (vedere i commenti).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Per verificare se una matrice di int
, double
o long
contiene un valore IntStream
, utilizzare DoubleStream
o LongStream
rispettivamente.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, ma non java.util.ArrayList
come ci si aspetta, la vera classe restituito è: java.util.Arrays.ArrayList<E>
definito come: public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Le matrici di riferimento sono errate. Per questo caso stiamo cercando un set. Dal momento che Java SE 9 abbiamo Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Dati String s, c'è un buon modo per testare se VALUES contiene s?"
VALUES.contains(s)
O (1).
Il tipo giusto , immutabile , O (1) e conciso . Bellissimo.*
Giusto 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à che è molto cattiva. Non modificare la statica e non consentire ad altri codici di farlo. Come minimo assoluto, il campo dovrebbe essere privato:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Nota, puoi effettivamente rilasciare il new String[];
bit.)
Le matrici di riferimento sono ancora errate e 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 proprio agio se questo fosse avvolto Collections.unmodifiableSet
- potrebbe anche essere reso pubblico.)
(* Per essere un po 'più sul marchio, l'API delle collezioni è prevedibilmente ancora priva di tipi di raccolta immutabili e la sintassi è ancora troppo prolissa, per i miei gusti.)
Arrays.asList
)?
TreeSet
sarebbe O(log n)
. HashSet
gli s sono ridimensionati in modo tale che il numero medio di elementi in un bucket sia approssimativamente costante. Almeno per array fino a 2 ^ 30. Potrebbero esserci effetti, per esempio, cache hardware che l'analisi big-O ignora. Suppone inoltre che la funzione hash funzioni in modo efficace.
È possibile utilizzare ArrayUtils.contains
da Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Si noti che questo metodo restituisce false
se l'array passato è null
.
Ci sono anche metodi disponibili per array primitivi di tutti i tipi.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Basta semplicemente 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:
La v != null
condizione è costante all'interno del metodo. Valuta sempre allo stesso valore booleano durante la chiamata del metodo. Quindi, se l'input array
è grande, è più efficiente valutare questa condizione una sola volta e possiamo usare una condizione semplificata / più veloce all'interno del for
loop in base al risultato. Il contains()
metodo migliorato :
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;
}
Collection.contains(Object)
Arrays
e ArrayList
risulta che questo non è necessariamente più veloce della versione che utilizza Arrays.asList(...).contains(...)
. Il sovraccarico di creazione di un ArrayList
è estremamente piccolo e ArrayList.contains()
utilizza un loop più intelligente (in realtà utilizza due loop diversi) rispetto a quello mostrato sopra (JDK 7).
Quattro modi diversi per verificare se un array contiene un valore
1) Utilizzo dell'elenco:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Utilizzando 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 seguente è errato, è elencato qui per completezza. binarySearch () può essere utilizzato SOLO su array ordinati. Di seguito troverai il risultato strano. Questa è l'opzione migliore quando l'array viene ordinato.
public static boolean binarySearch(String[] arr, String targetValue) {
int a = Arrays.binarySearch(arr, targetValue);
return a > 0;
}
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
(a >= 0)
era corretta, basta controllare i documenti , dicono "Nota che questo garantisce che il valore di ritorno sarà> = 0 se e solo se viene trovata la chiave".
Se l'array non è ordinato, dovrai scorrere su tutto ed effettuare una chiamata uguale a ciascuno.
Se l'array è ordinato, è possibile eseguire una ricerca binaria, ce n'è uno nella classe Array .
In generale, se hai intenzione di fare molti controlli di appartenenza, potresti voler archiviare tutto in un set, non in un array.
Per quello che vale ho eseguito un test confrontando i 3 suggerimenti per la velocità. Ho generato numeri interi casuali, li ho convertiti in una stringa e li ho aggiunti a un array. Ho quindi cercato il numero / stringa più alto possibile, che sarebbe uno scenario peggiore per il asList().contains()
.
Quando si utilizzava una dimensione di array di 10 K i risultati erano:
Ordina e cerca: 15 Ricerca binaria: 0 asList.contains: 0
Quando si utilizza un array da 100 K i risultati sono stati:
Ordina e cerca: 156 Ricerca binaria: 0 asList.contains: 32
Quindi, se l'array viene creato in ordine, la ricerca binaria è la più veloce, altrimenti asList().contains
sarebbe la strada da percorrere. Se hai molte ricerche, potrebbe essere utile ordinare l'array in modo da poter usare la ricerca binaria. Tutto dipende dalla tua applicazione.
Penso che questi siano 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));
}
}
Invece di utilizzare anche la sintassi di inizializzazione rapida dell'array, è possibile inizializzarla immediatamente come Elenco in 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");
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);
}
anyMatch
JavaDoc lo afferma "...May not evaluate the predicate on all elements if not necessary for determining the result."
, quindi potrebbe non essere necessario continuare l'elaborazione dopo aver trovato una corrispondenza.
È possibile utilizzare la classe Arrays per eseguire una ricerca binaria per il valore. Se il tuo array non è ordinato, dovrai utilizzare le funzioni di ordinamento nella stessa classe per ordinare l'array, quindi cercare attraverso di esso.
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;
}
In realtà, se usi HashSet <String> come proposto da Tom Hawtin, non devi preoccuparti dell'ordinamento e la tua velocità è la stessa della ricerca binaria su un array preordinato, probabilmente anche più veloce.
Dipende tutto da come è impostato il tuo codice, ovviamente, ma da dove mi trovo, l'ordine sarebbe:
Su un array non ordinato:
Su un array ordinato:
Quindi, in entrambi i casi, HashSet per la vittoria.
Se disponi della libreria di raccolte di Google, la risposta di Tom può essere semplificata molto utilizzando ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
Questo rimuove davvero molto disordine dall'inizializzazione proposta
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Una possibile soluzione:
import java.util.Arrays;
import java.util.List;
public class ArrayContainsElement {
public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");
public static void main(String args[]) {
if (VALUES.contains("AB")) {
System.out.println("Contains");
} else {
System.out.println("Not contains");
}
}
}
Gli sviluppatori fanno spesso:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Il codice sopra funziona, ma non è necessario convertire un elenco da impostare per primo. La conversione di un elenco in un set richiede tempo aggiuntivo. Può essere semplice come:
Arrays.asList(arr).contains(targetValue);
o
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Il primo è più leggibile del secondo.
L'uso di un semplice ciclo è il modo più efficiente per farlo.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Per gentile concessione di Programcreek
In Java 8 usa Stream.
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
Per matrici di lunghezza limitata, utilizzare quanto segue (come indicato da Camickr ). Questo è lento per controlli ripetuti, specialmente per array più lunghi (ricerca lineare).
Arrays.asList(...).contains(...)
Per prestazioni veloci se si verifica ripetutamente un insieme più ampio di elementi
Un array è la struttura sbagliata. Usa a TreeSet
e aggiungi ogni elemento ad esso. Ordina gli elementi e ha un exist()
metodo rapido (ricerca binaria).
Se gli elementi implementano Comparable
e si desidera l' TreeSet
ordinamento di conseguenza:
ElementClass.compareTo()
il metodo deve essere compatibile con ElementClass.equals()
: vedi Triadi che non si presentano per combattere? (Java Set manca un elemento)
TreeSet myElements = new TreeSet();
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
// *Alternatively*, if an array is forceably provided from other code:
myElements.addAll(Arrays.asList(myArray));
Altrimenti, usa il tuo Comparator
:
class MyComparator implements Comparator<ElementClass> {
int compareTo(ElementClass element1; ElementClass element2) {
// Your comparison of elements
// Should be consistent with object equality
}
boolean equals(Object otherComparator) {
// Your equality of comparators
}
}
// construct TreeSet with the comparator
TreeSet myElements = new TreeSet(new MyComparator());
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
Il payoff: controlla l'esistenza di alcuni elementi:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
è più veloce (O (1)) e non richiede l'ordinamento.
Prova questo:
ArrayList<Integer> arrlist = new ArrayList<Integer>(8);
// use add() method to add elements in the list
arrlist.add(20);
arrlist.add(25);
arrlist.add(10);
arrlist.add(15);
boolean retval = arrlist.contains(10);
if (retval == true) {
System.out.println("10 is contained in the list");
}
else {
System.out.println("10 is not contained in the list");
}
Utilizzare quanto segue (il contains()
metodo èArrayUtils.in()
in questo codice):
ObjectUtils.java
public class ObjectUtils{
/**
* A null safe method to detect if two objects are equal.
* @param object1
* @param object2
* @return true if either both objects are null, or equal, else returns false.
*/
public static boolean equals(Object object1, Object object2){
return object1==null ? object2==null : object1.equals(object2);
}
}
ArrayUtils.java
public class ArrayUtils{
/**
* Find the index of of an object is in given array, starting from given inclusive index.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @param start The index from where the search must start.
* @return Index of the given object in the array if it is there, else -1.
*/
public static <T> int indexOf(final T[] ts, final T t, int start){
for(int i = start; i < ts.length; ++i)
if(ObjectUtils.equals(ts[i], t))
return i;
return -1;
}
/**
* Find the index of of an object is in given array, starting from 0;
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return indexOf(ts, t, 0)
*/
public static <T> int indexOf(final T[] ts, final T t){
return indexOf(ts, t, 0);
}
/**
* Detect if the given object is in the given array.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return If indexOf(ts, t) is greater than -1.
*/
public static <T> boolean in(final T[] ts, final T t){
return indexOf(ts, t) > -1 ;
}
}
Come puoi vedere nel codice sopra, ci sono altri metodi di utilità ObjectUtils.equals()
e ArrayUtils.indexOf()
che sono stati usati anche in altri luoghi.
Verificare questo
String[] VALUES = new String[] {"AB","BC","CD","AE"};
String s;
for(int i=0; i< VALUES.length ; i++)
{
if ( VALUES[i].equals(s) )
{
// do your stuff
}
else{
//do your stuff
}
}
else
per ogni elemento che non corrisponde (quindi se stai cercando "AB" in quell'array, ci andrà 3 volte, poiché 3 dei valori non sono "AB ").
Arrays.asList () -> quindi chiamare il metodo Includes () funzionerà sempre, ma un algoritmo di ricerca è molto meglio poiché non è necessario creare un wrapper di elenco leggero attorno all'array, che è ciò che fa Arrays.asList () .
public boolean findString(String[] strings, String desired){
for (String str : strings){
if (desired.equals(str)) {
return true;
}
}
return false; //if we get here… there is no desired String, return false.
}
Arrays.asList
non è O (n). È solo un involucro leggero. Dai un'occhiata all'implementazione.
Se non vuoi che faccia distinzione tra maiuscole e minuscole
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Utilizzare Array.BinarySearch(array,obj)
per trovare l'oggetto dato in array o no.
Esempio:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false - non esiste
Array.BinarySearch
e Array.FindIndex
sono metodi .NET e non esistono in Java.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Crea un valore booleano inizialmente impostato su false. Esegui un ciclo per verificare ogni valore nell'array e confrontalo con il valore che stai verificando. Se mai ottieni una corrispondenza, imposta booleano su true e interrompi il looping. Quindi asserire che il booleano è vero.
Prova a utilizzare il metodo di test del predicato Java 8
Ecco un esempio completo di esso.
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Test {
public static final List<String> VALUES = Arrays.asList("AA", "AB", "BC", "CD", "AE");
public static void main(String args[]) {
Predicate<String> containsLetterA = VALUES -> VALUES.contains("AB");
for (String i : VALUES) {
System.out.println(containsLetterA.test(i));
}
}
}
http://mytechnologythought.blogspot.com/2019/10/java-8-predicate-test-method-example.html
https://github.com/VipulGulhane1/java8/blob/master/Test.java
l'uso di a Spliterator
impedisce la generazione non necessaria di a List
boolean found = false; // class variable
String search = "AB";
Spliterator<String> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
while( (! found) && spl.tryAdvance(o -> found = o.equals( search )) );
found == true
se search
è contenuto nell'array
questo fa lavoro per array di primitive
public static final int[] VALUES = new int[] {1, 2, 3, 4};
boolean found = false; // class variable
int search = 2;
Spliterator<Integer> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
…
Dato che ho a che fare con Java di basso livello che usa i tipi primitivi byte e byte [], il meglio che ho ottenuto è di bytes-java https://github.com/patrickfav/bytes-java sembra un ottimo lavoro
Puoi verificarlo con due metodi
A) Convertendo l'array in stringa e quindi controllare la stringa richiesta con il metodo .contains
String a=Arrays.toString(VALUES);
System.out.println(a.contains("AB"));
System.out.println(a.contains("BC"));
System.out.println(a.contains("CD"));
System.out.println(a.contains("AE"));
B) questo è un metodo più efficace
Scanner s=new Scanner(System.in);
String u=s.next();
boolean d=true;
for(int i=0;i<VAL.length;i++)
{
if(VAL[i].equals(u)==d)
System.out.println(VAL[i] +" "+u+VAL[i].equals(u));
}