Quiero filtrar un java.util.Collection
basado en un predicado.
java
collections
filter
Kevin Wong
fuente
fuente
persons.removeIf(p -> p.getAge() <= 16);
Suponiendo que está utilizando Java 1.5 y que no puede agregar Google Collections , haría algo muy similar a lo que hicieron los chicos de Google. Esta es una ligera variación en los comentarios de Jon.
Primero agregue esta interfaz a su base de código.
Sus implementadores pueden responder cuando cierto predicado es verdadero de cierto tipo. Por ejemplo, si
T
estuvieraUser
eAuthorizedUserPredicate<User>
implementeIPredicate<T>
,AuthorizedUserPredicate#apply
devuelve si el paseUser
está autorizado.Luego, en alguna clase de utilidad, podrías decir
Entonces, suponiendo que tiene el uso de lo anterior podría ser
Si el rendimiento en la verificación lineal es preocupante, entonces podría querer tener un objeto de dominio que tenga la colección de destino. El objeto de dominio que tiene la colección de destino tendría una lógica de filtrado para los métodos que inicializan, agregan y configuran la colección de destino.
ACTUALIZAR:
En la clase de utilidad (digamos Predicate), he agregado un método de selección con una opción para el valor predeterminado cuando el predicado no devuelve el valor esperado, y también una propiedad estática para los parámetros que se usarán dentro del nuevo IPredicate.
El siguiente ejemplo busca objetos faltantes entre colecciones:
El siguiente ejemplo busca una instancia en una colección y devuelve el primer elemento de la colección como valor predeterminado cuando no se encuentra la instancia:
ACTUALIZACIÓN (después del lanzamiento de Java 8):
Han pasado varios años desde que yo (Alan) publiqué esta respuesta por primera vez, y todavía no puedo creer que esté acumulando puntos SO para esta respuesta. En cualquier caso, ahora que Java 8 ha introducido cierres en el lenguaje, mi respuesta ahora sería considerablemente diferente y más simple. Con Java 8, no hay necesidad de una clase de utilidad estática distinta. Entonces, si desea encontrar el primer elemento que coincida con su predicado.
La API de JDK 8 para opcionales tiene la capacidad de
get()
,isPresent()
,orElse(defaultUser)
,orElseGet(userSupplier)
yorElseThrow(exceptionSupplier)
, así como otras funciones 'monádicos' tales comomap
,flatMap
yfilter
.Si desea simplemente recopilar todos los usuarios que coinciden con el predicado, utilice
Collectors
para finalizar la secuencia en la colección deseada.Consulte aquí para obtener más ejemplos sobre cómo funcionan las transmisiones Java 8.
fuente
val authorized = for (user <- users if user.isAuthorized) yield user
Utilice CollectionUtils.filter (Collection, Predicate) , de Apache Commons.
fuente
La "mejor" forma es una solicitud demasiado amplia. ¿Es "más corto"? "Lo más rápido"? "Legible"? ¿Filtrar en el lugar o en otra colección?
La forma más simple (pero no más legible) es iterarlo y usar el método Iterator.remove ():
Ahora, para hacerlo más legible, puede envolverlo en un método de utilidad. Luego invente una interfaz IPredicate, cree una implementación anónima de esa interfaz y haga algo como:
donde filterInPlace () itera la colección y llama a Predicate.keepIt () para saber si la instancia se mantendrá en la colección.
Realmente no veo una justificación para traer una biblioteca de terceros solo para esta tarea.
fuente
stream()
función, pero no todos pueden jugar con los juguetes más nuevos: PConsidere Google Collections para un marco de Colecciones actualizado que admita genéricos.
ACTUALIZACIÓN : La biblioteca de colecciones de google ahora está en desuso. En su lugar, debe usar la última versión de Guava . Todavía tiene las mismas extensiones al marco de colecciones, incluido un mecanismo de filtrado basado en un predicado.
fuente
Espera a Java 8:
fuente
personList.removeIf(p -> p.age < 30);
Menos detallado. Además, he oído hablar de comenzar la ejecución de API que aceptar y volverStream
s en lugar deCollection
s porqueStream
s son muy útiles y rápido, pero ir a / de ellos es lento.Desde el lanzamiento temprano de Java 8, puede intentar algo como:
Por ejemplo, si tuviera una lista de enteros y quisiera filtrar los números que son> 10 y luego imprimir esos números en la consola, podría hacer algo como:
fuente
Voy a tirar RxJava en el anillo, que también está disponible en Android . RxJava puede no ser siempre la mejor opción, pero le dará más flexibilidad si desea agregar más transformaciones a su colección o manejar errores durante el filtrado.
Salida:
Más detalles sobre RxJava
filter
se pueden encontrar aquí .fuente
La puesta en marcha:
El uso:
fuente
¿Qué tal un Java simple y directo?
Simple, legible y fácil (¡y funciona en Android!) Pero si está utilizando Java 8, puede hacerlo en una sola línea:
Tenga en cuenta que toList () se importa estáticamente
fuente
¿Está seguro de que desea filtrar la Colección en sí, en lugar de un iterador?
ver org.apache.commons.collections.iterators.FilterIterator
o usando la versión 4 de apache commons org.apache.commons.collections4.iterators.FilterIterator
fuente
Veamos cómo filtrar una lista JDK incorporada y una lista MutableList usando Eclipse Collections .
Si quisiera filtrar los números menores que 3, esperaría los siguientes resultados.
A continuación, le mostramos cómo puede filtrar utilizando un Java 8 lambda como
Predicate
.Así es como puede filtrar usando una clase interna anónima como
Predicate
.Aquí hay algunas alternativas para filtrar listas JDK y Eclipse Collections MutableLists usando la fábrica de Predicados .
Aquí hay una versión que no asigna un objeto para el predicado, utilizando la fábrica Predicates2 en su lugar con el
selectWith
método que toma aPredicate2
.A veces quieres filtrar en una condición negativa. Hay un método especial en Eclipse Collections para eso llamado
reject
.El método
partition
devolverá dos colecciones, que contienen los elementos seleccionados por y rechazados porPredicate
.Nota: Soy un committer para Eclipse Collections.
fuente
removeIf
en una lista o conjunto de primitivas?Con ForEach DSL puedes escribir
Dada una colección de [The, quick, brown, fox, jumps, over, the, lazy, dog], esto resulta en [quick, brown, jumps, over, lazy], es decir, todas las cadenas de más de tres caracteres.
Todos los estilos de iteración admitidos por ForEach DSL son
AllSatisfy
AnySatisfy
Collect
Counnt
CutPieces
Detect
GroupedBy
IndexOf
InjectInto
Reject
Select
Para obtener más detalles, consulte https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach
fuente
El método Collections2.filter (Collection, Predicate) en la biblioteca Guava de Google hace exactamente lo que estás buscando.
fuente
Como java 9
Collectors.filtering
está habilitado:Por lo tanto, el filtrado debe ser:
Ejemplo:
fuente
Esto, combinado con la falta de cierres reales, es mi mayor queja para Java. Honestamente, la mayoría de los métodos mencionados anteriormente son bastante fáciles de leer y REALMENTE eficientes; sin embargo, después de pasar tiempo con .Net, Erlang, etc., la comprensión de listas integrada a nivel de lenguaje hace que todo sea mucho más limpio. Sin adiciones a nivel de lenguaje, Java no puede ser tan limpio como muchos otros idiomas en esta área.
Si el rendimiento es una gran preocupación, las colecciones de Google son el camino a seguir (o escriba su propia utilidad de predicado simple). La sintaxis de Lambdaj es más legible para algunas personas, pero no es tan eficiente.
Y luego hay una biblioteca que escribí. Ignoraré cualquier pregunta con respecto a su eficiencia (sí, es tan malo) ... Sí, sé que está claramente basado en la reflexión, y no, en realidad no lo uso, pero funciona:
O
fuente
JFilter http://code.google.com/p/jfilter/ es el más adecuado para sus necesidades.
JFilter es una biblioteca de código abierto simple y de alto rendimiento para consultar la colección de beans Java.
Características clave
fuente
Escribí una clase Iterable extendida que admite la aplicación de algoritmos funcionales sin copiar el contenido de la colección.
Uso:
El código anterior se ejecutará realmente
fuente
Utilice el motor de consulta de recopilación (CQEngine) . Es, con mucho, la forma más rápida de hacer esto.
Consulte también: ¿Cómo consulta las colecciones de objetos en Java (Criterios / tipo SQL)?
fuente
Algunas respuestas realmente geniales aquí. A mí, me gustaría mantener las cosas tan simples y legibles como sea posible:
fuente
La solución simple anterior a Java8:
Desafortunadamente, esta solución no es completamente genérica, ya que genera una lista en lugar del tipo de la colección dada. Además, traer bibliotecas o escribir funciones que envuelvan este código me parece excesivo a menos que la condición sea compleja, pero luego puede escribir una función para la condición.
fuente
https://code.google.com/p/joquery/
Admite diferentes posibilidades,
Dada la colección,
de tipo,
Filtrar
Java 7
Java 8
También,
Clasificación (también disponible para Java 7)
Agrupación (también disponible para Java 7)
Uniones (también disponible para Java 7)
Dado,
Se puede unir como,
Expresiones
fuente
Mi respuesta se basa en eso de Kevin Wong, aquí como una línea usando
CollectionUtils
from spring y una expresión lambda de Java 8 .Esto es tan conciso y legible como cualquier otra alternativa que haya visto (sin usar bibliotecas basadas en aspectos)
Spring CollectionUtils está disponible a partir de la versión 4.0.2.RELEASE de Spring, y recuerde que necesita JDK 1.8 y nivel de idioma 8+.
fuente
Utilizando
java 8
, específicamentelambda expression
, puede hacerlo simplemente como en el siguiente ejemplo:donde para cada colección
product
internamyProducts
, siprod.price>10
, luego agregue este producto a la nueva lista filtrada.fuente
Necesitaba filtrar una lista dependiendo de los valores ya presentes en la lista. Por ejemplo, elimine todos los valores siguientes que sean menores que el valor actual. {2 5 3 4 7 5} -> {2 5 7}. O, por ejemplo, para eliminar todos los duplicados {3 5 4 2 3 5 6} -> {3 5 4 2 6}.
Esto se utilizará así.
fuente
Con guayaba:
fuente
En Java 8, puede usar directamente este método de filtro y luego hacerlo.
fuente