¿Cuál es la mejor manera de filtrar una colección Java?


Quiero filtrar un java.util.Collection basado en un predicado.

Author: user2864740, 2008-09-23

26 answers

Java 8 (2014) resuelve este problema usando flujos y lambdas en una línea de código:

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16).collect(Collectors.toList());

Aquí hay un tutorial .

Uso Collection#removeIf para modificar la colección en su lugar. (Nota: En este caso, el predicado eliminará los objetos que satisfagan el predicado):

persons.removeIf(p -> p.getAge() <= 16);

Lambdaj permite filtrar colecciones sin escribir bucles o clases internas:

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));

¿Puedes imaginar algo más legible?

Descargo de responsabilidad: Soy un colaborador en lambdaj

 554
Author: Mario Fusco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-20 19:23:48

Asumiendo que estás usando Java 1.5, y que no puedes agregar Google Collections, haría algo muy similar a lo que hicieron los chicos de Google. Esta es una ligera variación de los comentarios de Jon.

Primero agregue esta interfaz a su base de código.

public interface IPredicate<T> { boolean apply(T type); }

Sus implementadores pueden responder cuando cierto predicado es verdadero de cierto tipo. Por ejemplo, Si T eran User y AuthorizedUserPredicate<User> implementa IPredicate<T>, entonces AuthorizedUserPredicate#apply devuelve si el pasado en User es autorizar.

Entonces en alguna clase de utilidad, se podría decir

public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T element: target) {
        if (predicate.apply(element)) {
            result.add(element);
        }
    }
    return result;
}

Por lo tanto, suponiendo que usted tiene el uso de lo anterior podría ser

Predicate<User> isAuthorized = new Predicate<User>() {
    public boolean apply(User user) {
        // binds a boolean method in User to a reference
        return user.isAuthorized();
    }
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);

Si el rendimiento en la comprobació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 establecen la colección de destino.

ACTUALIZACIÓN:

En la clase de utilidad (digamos Predicado), he añadido un método select 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 utilizarán dentro del nuevo IPredicate.

public class Predicate {
    public static Object predicateParams;

    public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
        Collection<T> result = new ArrayList<T>();
        for (T element : target) {
            if (predicate.apply(element)) {
                result.add(element);
            }
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
        T result = null;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
        T result = defaultValue;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }
}

El siguiente ejemplo busca objetos faltantes entre colecciones:

List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
    new IPredicate<MyTypeA>() {
        public boolean apply(MyTypeA objectOfA) {
            Predicate.predicateParams = objectOfA.getName();
            return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
                public boolean apply(MyTypeB objectOfB) {
                    return objectOfB.getName().equals(Predicate.predicateParams.toString());
                }
            }) == null;
        }
    });

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:

MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
    return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));

ACTUALIZACIÓN (después del lanzamiento de Java 8):

Han pasado varios años desde que yo (Alan) publiqué por primera vez esta respuesta, y todavía no puedo creer que esté recolectando puntos por esta respuesta. En cualquier caso, ahora que Java 8 ha introducido cierres al 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. Así que si quieres encontrar el 1er elemento que coincide con su predicado.

final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).findFirst();

La API JDK 8 para opcionales tiene capacidad para get(), isPresent(), orElse(defaultUser), orElseGet(userSupplier) y orElseThrow(exceptionSupplier), así como otros "monádica" funciones tales como map, flatMap y filter.

Si simplemente desea recopilar todos los usuarios que coincidan con el predicado, use Collectors para terminar la secuencia en la colección deseada.

final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).collect(Collectors.toList());

Vea aquí para más ejemplos sobre cómo funcionan los flujos de Java 8.

 215
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-11 16:09:52
 87
Author: Kevin Wong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-17 06:11:33

"Mejor" camino es una solicitud demasiado amplia. ¿Es "más corto"? "Más rápido"? "Legible"? Filtrar en su lugar o en otra colección?

La forma más simple (pero no la más legible) es iterarla y usar Iterador.método remove ():

Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
  Foo foo = it.next();
  if( !condition(foo) ) it.remove();
}

Ahora, para que sea más legible, puede envolverlo en un método de utilidad. Luego inventa una interfaz IPredicate, crea una implementación anónima de esa interfaz y haz algo como:

CollectionUtils.filterInPlace(col,
  new IPredicate<Foo>(){
    public boolean keepIt(Foo foo) {
      return foo.isBar();
    }
  });

Donde filterInPlace () itera la colección y las llamadas Predicado.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.

 60
Author: Vladimir Dyuzhev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-17 16:26:29

Considere Google Collections para un marco de recopilación actualizado que admita genéricos.

ACTUALIZACIÓN : La biblioteca de Google collections ahora está obsoleta. Deberías usar la última versión de Guava en su lugar. Todavía tiene todas las mismas extensiones al framework de colecciones incluyendo un mecanismo para filtrar basado en un predicado.

 60
Author: Heath Borders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-13 19:26:35

Espere a Java 8:

List<Person> olderThan30 = 
  //Create a Stream from the personList
  personList.stream().
  //filter the element to select only those with age >= 30
  filter(p -> p.age >= 30).
  //put those filtered elements into a new List.
  collect(Collectors.toList());
 23
Author: gavenkoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-24 08:24:01

Desde el lanzamiento anticipado de Java 8, puedes probar algo como:

Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);

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:

List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);
 10
Author: Josh M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-27 21:41:55

Lanzaré RxJavaen el ring, 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 en su colección o manejar errores mientras filtra.

Observable.from(Arrays.asList(1, 2, 3, 4, 5))
    .filter(new Func1<Integer, Boolean>() {
        public Boolean call(Integer i) {
            return i % 2 != 0;
        }
    })
    .subscribe(new Action1<Integer>() {
        public void call(Integer i) {
            System.out.println(i);
        }
    });

Salida:

1
3
5

Se pueden encontrar más detalles sobre filter de RxJava aquí.

 9
Author: anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-14 23:25:12

La configuración:

public interface Predicate<T> {
  public boolean filter(T t);
}

void filterCollection(Collection<T> col, Predicate<T> predicate) {
  for (Iterator i = col.iterator(); i.hasNext();) {
    T obj = i.next();
    if (predicate.filter(obj)) {
      i.remove();
    }
  }
}

El uso:

List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
  public boolean filter(MyObject obj) {
    return obj.shouldFilter();
  }
});
 6
Author: jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-23 16:41:27

¿Qué tal un Java simple y recto

 List<Customer> list ...;
 List<Customer> newList = new ArrayList<>();
 for (Customer c : list){
    if (c.getName().equals("dd")) newList.add(c);
 }

Simple, legible y fácil (y funciona en Android!) Pero si estás usando Java 8 puedes hacerlo en una línea dulce:

List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());

Tenga en cuenta que ToList() se importa estáticamente

 6
Author: Nestor Hernandez Loli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 05:03:57

¿Está seguro de que desea filtrar la Colección en sí, en lugar de un iterador?

Véase org.apache.común.colecciones.iteradores.FilterIterator

O usando la versión 4 de apache commons org.apache.común.colecciones 4.iteradores.FilterIterator

 6
Author: ykaganovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 08:43:33

Veamos cómo filtrar una lista JDK incorporada y una Lista de mutables usando Colecciones de Eclipse (anteriormente Colecciones de GS).

List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);

Si desea filtrar los números inferiores a 3, esperaría las siguientes salidas.

List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);

Así es como puedes filtrar usando una clase interna anónima como Predicate.

Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
    public boolean accept(Integer each)
    {
        return each < 3;
    }
};

Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));

Assert.assertEquals(selected, ecList.select(lessThan3));

Aquí hay algunas alternativas para filtrar listas JDK y Colecciones de Eclipse Listas mutables usando el Predicados fábrica.

Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));

Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));

Aquí hay una versión que no asigna un objeto para el predicado, utilizando la fábrica Predicates2 en su lugar con el método selectWith que toma un Predicate2.

Assert.assertEquals(
    selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));

A Veces desea filtrar en una condición negativa. Hay un método especial en las Colecciones de Eclipse para eso llamado reject.

Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));

Assert.assertEquals(rejected, ecList.reject(lessThan3));

Así es como puedes filtrar usando un lambda Java 8 como el Predicate.

Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));

Assert.assertEquals(selected, gscList.select(each -> each < 3));
Assert.assertEquals(rejected, gscList.reject(each -> each < 3));

El método partition volverá dos colecciones, que contienen los elementos seleccionados y rechazados por el Predicate.

PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());

PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());

Nota: Soy un committer para las Colecciones de Eclipse.

 5
Author: Donald Raab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 04:20:22

Con el DSL ForEach puede escribir

import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;

Collection<String> collection = ...

for (Select<String> each : select(collection)) {
    each.yield = each.value.length() > 3;
}

Collection<String> result = $result();

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 soportados por el DSL ForEach son

  • AllSatisfy
  • AnySatisfy
  • Collect
  • Counnt
  • CutPieces
  • Detect
  • GroupedBy
  • IndexOf
  • InjectInto
  • Reject
  • Select

Para más detalles, consulte https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach

 4
Author: akuhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-03 16:20:21

Las Colecciones 2.filter (Collection, Predicate) método en La biblioteca de Guayaba de Google hace justo lo que estás buscando.

 4
Author: Kevin Wong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-09 21:19:44

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 idioma hace que todo sea mucho más limpio. Sin adiciones a nivel de lenguaje, Java simplemente no puede ser tan limpio como muchos otros idiomas en esta área.

Si el rendimiento es una gran preocupación, Google collections es el camino para ir (o escribir 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 se basa claramente en la reflexión, y no, en realidad no lo uso, pero funciona:

LinkedList<Person> list = ......
LinkedList<Person> filtered = 
           Query.from(list).where(Condition.ensure("age", Op.GTE, 21));

O

LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
 3
Author: jdc0589,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-23 03:55:48

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 Java beans.

Características principales

  • Soporte de colección (java.útil.Colección, java.útil.Map and Array) propiedades.
  • Soporte de colección dentro de colección de cualquier profundidad.
  • Soporte de consultas internas.
  • Soporte de consultas parametrizadas.
  • Puede filtrar 1 millones de registros en pocos 100 ms.
  • El filtro ( query) se da en formato json simple, es como las consultas Mangodb. A continuación se presentan algunos ejemplos.
  • {"id": {"le le": "10"}
    • donde la propiedad id del objeto es menor que igual a 10.
  • {"id": {"in in": ["0", " 100"]}}
    • donde la propiedad id del objeto es 0 o 100.
  • {"LineItems": {"lineAmount": "1"}}
    • donde la propiedad LineItems collection del tipo parametrizado tiene lineAmount igual a 1.
  • {"id and": [{"id":" 0"}, {"BillingAddress": {"city": "DEL"}}]}
    • donde la propiedad id es 0 y BillingAddress.propiedad de la ciudad es DEL.
  • {"LineItems": {"taxes": {"key": {"code":" GST"}, "value": {"gt gt": "1.01"}}}}
    • donde LineItems propiedad de colección de tipo parametrizado que tiene impuestos tipo de mapa propiedad de tipo parametrizado tiene código igual a valor GST mayor que 1.01.
  • {'or or': [{'code': '10'}, {'skus': {'price and': [{'price': {'in in':['20', '40']}}, {'código": "RedApple"}]}}]}
    • Seleccione todos los productos donde el código de producto es 10 o el precio de sku en 20 y 40 y el código de sku es "RedApple".
 2
Author: Kamran Ali Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-05 10:46:58

Escribí una clase iterable extendida que admite la aplicación de algoritmos funcionales sin copiar el contenido de la colección.

Uso:

List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }

Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
    public Boolean call(Integer n) throws FunctionalException
    {
        return n % 2 == 0;
    }
})

for( int n : filtered )
{
    System.out.println(n);
}

El código anterior ejecutará

for( int n : myList )
{
    if( n % 2 == 0 ) 
    {
        System.out.println(n);
    }
}
 2
Author: Vincent Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-23 15:50:02
 2
Author: npgall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:25

Desde java 9 Collectors.filtering está habilitado:

public static <T, A, R>
    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
                                 Collector<? super T, A, R> downstream)

Por lo tanto, el filtrado debe ser:

collection.stream().collect(Collectors.filtering(predicate, collector))

Ejemplo:

List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
            .collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
 2
Author: fbokovikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 13:59:00

La solución simple pre-Java8:

ArrayList<Item> filtered = new ArrayList<Item>(); 
for (Item item : items) if (condition(item)) filtered.add(item);

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 exagerado a menos que la condición sea compleja, pero luego puedes escribir una función para la condición.

 1
Author: Andrew McKnight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-03 19:15:32

Https://code.google.com/p/joquery /

Soporta diferentes posibilidades,

Dada la colección,

Collection<Dto> testList = new ArrayList<>();

De tipo,

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

Filtro

Java 7

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();

Java 8

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property(Dto::getId)
    .eq().value(1);
Collection<Dto> filtered = query.list();

También,

Filter<Dto> query = CQ.<Dto>filter()
        .from(testList)
        .where()
        .property(Dto::getId).between().value(1).value(2)
        .and()
        .property(Dto::grtText).in().value(new string[]{"a","b"});

Ordenar (también disponible para Java 7)

Filter<Dto> query = CQ.<Dto>filter(testList)
        .orderBy()
        .property(Dto::getId)
        .property(Dto::getName)
    Collection<Dto> sorted = query.list();

Grouping (también disponible para Java 7)

GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
        .group()
        .groupBy(Dto::getId)
    Collection<Grouping<Integer,Dto>> grouped = query.list();

Joins (también disponible para Java 7)

Dado,

class LeftDto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

class RightDto
{
    private int id;
    private int leftId;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getLeftId()
        {
            return leftId;
        }

    public int getText()
    {
        return text;
    }
}

class JoinedDto
{
    private int leftId;
    private int rightId;
    private String text;

    public JoinedDto(int leftId,int rightId,String text)
    {
        this.leftId = leftId;
        this.rightId = rightId;
        this.text = text;
    }

    public int getLeftId()
    {
        return leftId;
    }

    public int getRightId()
        {
            return rightId;
        }

    public int getText()
    {
        return text;
    }
}

Collection<LeftDto> leftList = new ArrayList<>();

Collection<RightDto> rightList = new ArrayList<>();

Se puede unir como,

Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
                .<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
                .on(LeftFyo::getId, RightDto::getLeftId)
                .transformDirect(selection ->  new JoinedDto(selection.getLeft().getText()
                                                     , selection.getLeft().getId()
                                                     , selection.getRight().getId())
                                 )
                .list();

Expresiones

Filter<Dto> query = CQ.<Dto>filter()
    .from(testList)
    .where()
    .exec(s -> s.getId() + 1).eq().value(2);
 1
Author: Low Flying Pelican,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-03 12:59:35

Mi respuesta se basa en eso de Kevin Wong, aquí como una sola línea usando CollectionUtils de spring y una expresión Java 8 lambda.

CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);

Esto es tan conciso y legible como cualquier alternativa que he visto (sin usar bibliotecas basadas en aspectos)

Spring CollectionUtils está disponible desde spring versión 4.0.2.LANZAMIENTO, y recuerde que necesita JDK 1.8 y nivel de idioma 8+.

 1
Author: vikingsteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-22 11:18:24

Algunas realmente grandes grandes respuestas aquí. Yo, me gustaría mantener thins tan simple y legible como sea posible:

public abstract class AbstractFilter<T> {

    /**
     * Method that returns whether an item is to be included or not.
     * @param item an item from the given collection.
     * @return true if this item is to be included in the collection, false in case it has to be removed.
     */
    protected abstract boolean excludeItem(T item);

    public void filter(Collection<T> collection) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<T> iterator = collection.iterator();
            while (iterator.hasNext()) {
                if (excludeItem(iterator.next())) {
                    iterator.remove();
                }
            }
        }
    }
}
 1
Author: Lawrence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-05 16:22:48

Usando java 8, específicamente lambda expression, puedes hacerlo simplemente como el siguiente ejemplo:

myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())

Donde para cada product dentro de myProducts colección, si prod.price>10, a continuación, añadir este producto a la nueva lista filtrada.

 0
Author: hd84335,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-12 21:47:55

Con Guayaba:

Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);

Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
    @Override
    public boolean apply(Integer i) {
        return i % 2 == 0;
    }
});

System.out.println(collection); // Prints 1, 3, 5
 0
Author: ZhekaKozlov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-15 09:26:44

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}.

public class Filter {
    public static <T> void List(List<T> list, Chooser<T> chooser) {
        List<Integer> toBeRemoved = new ArrayList<>();
        leftloop:
        for (int right = 1; right < list.size(); ++right) {
            for (int left = 0; left < right; ++left) {
                if (toBeRemoved.contains(left)) {
                    continue;
                }
                Keep keep = chooser.choose(list.get(left), list.get(right));
                switch (keep) {
                    case LEFT:
                        toBeRemoved.add(right);
                        continue leftloop;
                    case RIGHT:
                        toBeRemoved.add(left);
                        break;
                    case NONE:
                        toBeRemoved.add(left);
                        toBeRemoved.add(right);
                        continue leftloop;
                }
            }
        }

        Collections.sort(toBeRemoved, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        for (int i : toBeRemoved) {
            if (i >= 0 && i < list.size()) {
                list.remove(i);
            }
        }
    }

    public static <T> void List(List<T> list, Keeper<T> keeper) {
        Iterator<T> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (!keeper.keep(iterator.next())) {
                iterator.remove();
            }
        }
    }

    public interface Keeper<E> {
        boolean keep(E obj);
    }

    public interface Chooser<E> {
        Keep choose(E left, E right);
    }

    public enum Keep {
        LEFT, RIGHT, BOTH, NONE;
    }
}

Esto se usará así.

List<String> names = new ArrayList<>();
names.add("Anders");
names.add("Stefan");
names.add("Anders");
Filter.List(names, new Filter.Chooser<String>() {
    @Override
    public Filter.Keep choose(String left, String right) {
        return left.equals(right) ? Filter.Keep.LEFT : Filter.Keep.BOTH;
    }
});
 0
Author: Fredrik Metcalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-15 14:28:05