Quiero verificar si a List
contiene un objeto que tiene un campo con un cierto valor. Ahora, podría usar un bucle para pasar y verificar, pero tenía curiosidad por saber si había algo más eficiente en el código.
Algo como;
if(list.contains(new Object().setName("John"))){
//Do some stuff
}
Sé que el código anterior no hace nada, es solo para demostrar aproximadamente lo que estoy tratando de lograr.
Además, solo para aclarar, la razón por la que no quiero usar un bucle simple es porque este código irá actualmente dentro de un bucle que está dentro de un bucle que está dentro de un bucle. Para facilitar la lectura, no quiero seguir agregando bucles a estos bucles. Entonces me pregunté si había alternativas simples (ish).
equals(Object)
método de su objeto personalizado?for(Person p:list) if (p.getName().equals("John") return true; return false;
Me temo que no encontrarás una manera más concisa en Java.p.equals(p)
debe ser cierto, así que estoy confundido con lo que estás tratando de lograr. Espero que si hace una nueva pregunta pueda obtener una mejor ayuda.Respuestas:
Corrientes
Si está utilizando Java 8, quizás podría intentar algo como esto:
O, alternativamente, podría intentar algo como esto:
Este método devolverá
true
siList<MyObject>
contiene unMyObject
con el nombrename
. Si desea realizar una operación en cada uno de losMyObject
sgetName().equals(name)
, puede intentar algo como esto:Donde
o
representa unaMyObject
instancia.Alternativamente, como sugieren los comentarios (Gracias MK10), puede usar el
Stream#anyMatch
método:fuente
public boolean
. Además, es posible que desee utilizarObjects.equals()
en caso de queo.getName()
pueda sernull
.null
verificaciones, en lugar de solo una (la mía).return list.stream().anyMatch(o -> o.getName().equals(name));
java.util.Objects
para la comparación nula-segura.return list.stream().anyMatch(o -> Objects.euqals(o.getName(), name);
Si desea verificar los objetos en la secuencia para nulo, puede agregar un.filter(Objects::nonNull)
antes de anyMatch.Tienes dos opciones.
1. La primera opción, que es preferible, es anular el método `equals ()` en su clase Object.
Digamos, por ejemplo, que tiene esta clase de objeto:
Ahora digamos que solo le importa el nombre de MyObject, que debería ser único, por lo que si dos `MyObject`s tienen el mismo nombre, deberían considerarse iguales. En ese caso, desearía anular el método `equals ()` (y también el método `hashcode ()`) para que compare los nombres para determinar la igualdad.
Una vez que haya hecho esto, puede verificar si una Colección contiene un MyObject con el nombre "foo" de la siguiente manera:
Sin embargo, esto podría no ser una opción para usted si:
Si cualquiera de estos es el caso, querrá la opción 2:
2. Escriba su propio método de utilidad:
Alternativamente, puede extender ArrayList (o alguna otra colección) y luego agregarle su propio método:
Desafortunadamente no hay una mejor manera de evitarlo.
fuente
Google guayaba
Si usa Guava , puede adoptar un enfoque funcional y hacer lo siguiente
que se ve un poco detallado. Sin embargo, el predicado es un objeto y puede proporcionar diferentes variantes para diferentes búsquedas. Observe cómo la biblioteca misma separa la iteración de la colección y la función que desea aplicar. No tiene que anular
equals()
un comportamiento particular.Como se indica a continuación, el marco java.util.Stream integrado en Java 8 y posterior proporciona algo similar.
fuente
Iterables.any(list, predicate)
, que es prácticamente lo mismo, y puede o no preferirlo estilísticamente.Así es como se hace usando Java 8+:
fuente
Collection.contains()
se implementa llamandoequals()
a cada objeto hasta que uno regresetrue
.Entonces, una forma de implementar esto es anular,
equals()
pero por supuesto, solo puede tener uno igual.Los marcos como la guayaba, por lo tanto, utilizan predicados para esto. Con
Iterables.find(list, predicate)
, puede buscar campos arbitrarios poniendo la prueba en el predicado.Otros lenguajes construidos sobre la VM tienen esto incorporado. En Groovy , por ejemplo, simplemente escribe:
Java 8 también nos facilitó la vida:
Si te importan cosas como esta, te sugiero el libro "Más allá de Java". Contiene muchos ejemplos de las numerosas deficiencias de Java y de cómo otros idiomas funcionan mejor.
fuente
equals()
es muy limitada. Significa verificar la "identidad del objeto", lo que sea que eso signifique para alguna clase de objetos. Si agregaste una marca que campos deberían incluirse, eso podría causar todo tipo de problemas. Recomiendo encarecidamente que no lo haga.def result = list.find{ it.name == 'John' }
Oracle / JCP debe ser demandado por crímenes de guerra contra programadores.Búsqueda binaria
Puede usar Collections.binarySearch para buscar un elemento en su lista (suponiendo que la lista esté ordenada):
que devolverá un número negativo si el objeto no está presente en la colección o devolverá el
index
del objeto. Con esto puede buscar objetos con diferentes estrategias de búsqueda.fuente
Mapa
Puede crear un
Hashmap<String, Object>
utilizando uno de los valores como clave y luego ver siyourHashMap.keySet().contains(yourValue)
devuelve verdadero.fuente
Colecciones Eclipse
Si está usando Eclipse Collections , puede usar el
anySatisfy()
método. Adapta tuList
enListAdapter
o cambia tuList
aListIterable
si es posible.Si realiza operaciones como esta con frecuencia, es mejor extraer un método que responda si el tipo tiene el atributo.
Puede usar la forma alternativa
anySatisfyWith()
junto con una referencia de método.Si no puede cambiarlo
List
por unoListIterable
, así es como lo usaríaListAdapter
.Nota: Soy un committer para las selecciones de Eclipse.
fuente
Predicate
Si no utiliza Java 8, o una biblioteca que le brinda más funcionalidad para manejar colecciones, podría implementar algo que sea más reutilizable que su solución.
Estoy usando algo así, tengo una interfaz de predicado y la paso a mi clase de utilidad.
¿Cuál es la ventaja de hacer esto a mi manera? tiene un método que se ocupa de buscar en cualquier tipo de colección. y no tiene que crear métodos separados si desea buscar por un campo diferente. Todo lo que necesita hacer es proporcionar un predicado diferente que se pueda destruir tan pronto como ya no sea útil.
si desea usarlo, todo lo que necesita hacer es llamar al método y definir su predicado
fuente
Aquí hay una solución usando guayaba
fuente
contains
El método se utilizaequals
internamente. Por lo tanto, debe anular elequals
método para su clase según su necesidad.Por cierto, esto no parece sintácticamente correcto:
fuente
this
.equals
para un caso de uso único, a menos que tenga sentido para la clase en general. Sería mucho mejor escribir el bucle.Si necesita realizar esto
List.contains(Object with field value equal to x)
repetidamente, una solución simple y eficiente sería:Entonces el
List.contains(Object with field value equal to x)
tendría el mismo resultado quefieldOfInterestValues.contains(x);
fuente
también puedes
anyMatch()
usar:fuente
A pesar de JAVA 8 SDK, hay muchas herramientas de colección que las bibliotecas pueden ayudarlo a trabajar, por ejemplo: http://commons.apache.org/proper/commons-collections/
fuente