length - ¿Cómo determinar si una matriz contiene un valor particular en Java?
java array push (25)
Para matrices de longitud limitada, use lo siguiente (como se indica en camickr ). Esto es lento para verificaciones repetidas, especialmente para arreglos más largos (búsqueda lineal).
Arrays.asList(...).contains(...)
Para un rendimiento rápido si se verifica repetidamente contra un conjunto más grande de elementos
Una matriz es la estructura incorrecta. Use un
TreeSet
y agregue cada elemento a él. Ordena los elementos y tiene un método rápido deexist()
(búsqueda binaria).Si los elementos implementan
Comparable
y desea que elTreeSet
consecuencia:ElementClass.compareTo()
métodoElementClass.compareTo()
debe ser compatible conElementClass.equals()
: ¿ver Triadas que no aparecen para luchar? (Java Set falta 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));
De lo contrario, usa tu propio
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);
La recompensa: comprobar la existencia de algún elemento:
// Fast binary search through sorted elements (performance ~ log(size)): boolean containsElement = myElements.exists(someElement);
Tengo una String[]
con valores así:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dado String s
, ¿hay una buena manera de probar si VALUES
contiene s
?
Arrays.asList () ->, entonces, llamar al método contiene () siempre funcionará, pero un algoritmo de búsqueda es mucho mejor, ya que no es necesario crear una envoltura de lista ligera alrededor de la matriz, que es lo que hace 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.
}
Con Java 8 puede crear una secuencia y verificar si alguna de las entradas de la secuencia coincide con "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
O como método genérico:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
Crear un booleano inicialmente establecido en falso. Ejecute un bucle para verificar cada valor en la matriz y comparar con el valor con el que está comparando. Si alguna vez obtiene una coincidencia, establezca boolean en verdadero y detenga el bucle. Luego afirma que el booleano es verdadero.
En Java 8 usa Streams.
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);
En lugar de usar la sintaxis de inicialización de matriz rápida para usted, solo puede iniciarlo como una lista de forma similar utilizando el método Arrays.asList, por ejemplo:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Luego puedes hacer (como arriba): STRINGS.contains("the string you want to find");
En realidad, si usa HashSet como Tom Hawtin propuso, no necesita preocuparse por la clasificación y su velocidad es la misma que con la búsqueda binaria en una matriz preclasificada, probablemente incluso más rápida.
Todo depende de cómo esté configurado su código, obviamente, pero desde mi punto de vista, el orden sería:
En una matriz sin clasificar:
- HashSet
- comoLista
- ordenar y binario
En una matriz ordenada:
- HashSet
- Binario
- comoLista
Así que de cualquier manera, HashSet ftw
Llego muy tarde para unirme a esta discusión, pero desde que abordé este problema, cuando lo enfrenté hace unos años, era un poco diferente a las otras respuestas ya publicadas aquí, estoy publicando la solución que usé en ese momento, aquí, en caso de que alguien lo encuentre útil: (el método contains()
es ArrayUtils.in()
en este código).
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 ;
}
}
Como puede ver en el código anterior, hay otros métodos de utilidad ObjectUtils.equals()
y ArrayUtils.indexOf()
, que también se usaron en otros lugares.
Los desarrolladores a menudo hacen:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
El código anterior funciona, pero no es necesario convertir una lista para establecer primero. Convertir una lista en un conjunto requiere tiempo adicional. Puede tan simple como:
Arrays.asList(arr).contains(targetValue);
o
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
El primero es más legible que el segundo.
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:
La condición v != null
es constante dentro del método, siempre se evalúa al mismo valor booleano durante la llamada al método. Entonces, si la array
entrada 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 bucle for
basado en el resultado. El método mejorado contains()
:
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;
}
Mira esto
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
}
}
ObStupidAnswer (pero creo que hay una lección aquí en alguna parte):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Por lo que vale la pena hice una prueba comparando las 3 sugerencias de velocidad. Generé enteros aleatorios, los convertí en una cadena y los agregué a una matriz. Luego busqué el número / cadena más alto posible, que sería el peor de los casos para asList (). Contiene ().
Cuando se usa un tamaño de matriz de 10 K, los resultados son:
Sort & Search : 15 Binary Search : 0 asList.contains : 0
Cuando se usa una matriz de 100 K, los resultados son:
Sort & Search : 156 Binary Search : 0 asList.contains : 32
Por lo tanto, si la matriz se crea en orden, la búsqueda binaria es la más rápida, de lo contrario, asList () será 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 su aplicación.
Pensaría 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));
}
}
Prueba esto:
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");
}
Puede utilizar la clase Arrays para realizar una búsqueda binaria del valor. Si su matriz no está ordenada, tendrá que usar las funciones de clasificación en la misma clase para ordenar la matriz, y luego buscarla.
Puedes usar ArrayUtils.contains
desde Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Tenga en cuenta que este método devuelve false
si la matriz pasada 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.
}
Sólo 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 mala. Debería ser privado:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Tenga en cuenta que realmente puede soltar la new String[];
bit.)
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 paranoicas, como yo, pueden sentirse más cómodas si esto se envolvió en Collections.unmodifiableSet
. Collections.unmodifiableSet
no modificable, incluso podría hacerse público).
"Dado String s, ¿hay una buena manera de probar si VALUES contiene s?"
VALUES.contains(s)
O (1).
Si la matriz no está ordenada, tendrá que iterar sobre todo y hacer una llamada a iguales en cada uno.
Si la matriz está ordenada, puede hacer una búsqueda binaria, hay una en la clase Arrays .
En general, si va a realizar muchas comprobaciones de membresía, es posible que desee almacenar todo en un Conjunto, no en una matriz.
Si no quieres que sea sensible a las mayúsculas
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Si tiene la biblioteca de colecciones de Google, la respuesta de Tom se puede simplificar mucho usando ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
Esto realmente elimina una gran cantidad de desorden de la inicialización propuesta
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Una posible solución:
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");
}
}
}
Usar un bucle simple es la forma más eficiente de hacer esto.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Cortesía de Programcreek
Use Array.BinarySearch(array,obj)
para encontrar el objeto dado en array o no. Ex:
if (Array.BinarySearch(str, i) > -1)
-> true --existe
falso - no existe
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) Utilizando 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 de abajo es incorrecto, aparece aquí para completar. binarySearch () SOLO puede usarse en arreglos ordenados. Encontrarás que el resultado es raro a continuación. Esta es la mejor opción cuando se ordena la matriz.
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
Arrays.asList(yourArray).contains(yourValue)
Advertencia: esto no funciona para matrices de primitivos (ver los comentarios).
Desde java-8 ahora puedes usar Streams.
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Para verificar si una matriz de int
, double
o long
contiene un valor, use IntStream
, DoubleStream
o LongStream
respectivamente.
Ejemplo
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);