Artículo

Java Stream Filter y Predicate: Guía Completa con Ejemplos

Aprende a usar filter() y Predicate en Java Streams, cómo combinar condiciones con and(), or() y negate(), con ejemplos de código reales.

El método filter() de la API de Streams permite seleccionar únicamente los elementos que cumplen una condición determinada, definida a través de un Predicate. Es una de las operaciones intermedias más usadas junto a map().

¿Qué es filter() en un Stream?

filter() recibe un Predicate y devuelve un nuevo Stream que contiene solo los elementos para los que ese predicado devuelve true. Es una operación intermedia: no se ejecuta hasta que aparece una operación terminal en el pipeline.

¿Qué es un Predicate en Java?

Un Predicate<T> es una interfaz funcional que representa una función que recibe un objeto de tipo T y devuelve un boolean. Es, literalmente, una condición encapsulada como objeto.

Predicate<Integer> esPar = n -> n % 2 == 0;
System.out.println(esPar.test(4)); // true

Sintaxis básica de filter() con lambda

List<Integer> numeros = List.of(1, 2, 3, 4, 5, 6);

List<Integer> pares = numeros.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

// pares -> [2, 4, 6]

Combinar Predicates: and(), or(), negate()

Predicate<Integer> esPar = n -> n % 2 == 0;
Predicate<Integer> esMayorQueDiez = n -> n > 10;

Predicate<Integer> parYMayorQueDiez = esPar.and(esMayorQueDiez);
Predicate<Integer> parONegativo = esPar.or(n -> n < 0);
Predicate<Integer> esImpar = esPar.negate();

Estos métodos permiten construir condiciones complejas combinando predicados simples y reutilizables, en lugar de escribir expresiones lambda largas y difíciles de leer.

Ejemplo práctico: filtrar una lista de objetos

record Empleado(String nombre, String departamento, double salario) {}

List<Empleado> empleados = List.of(
    new Empleado("Ana", "IT", 2800),
    new Empleado("Luis", "Ventas", 2100),
    new Empleado("Carla", "IT", 3200)
);

Predicate<Empleado> esDeIT = e -> e.departamento().equals("IT");
Predicate<Empleado> ganaMasDe3000 = e -> e.salario() > 3000;

List<Empleado> resultado = empleados.stream()
    .filter(esDeIT.and(ganaMasDe3000))
    .collect(Collectors.toList());

// resultado -> [Carla]

Reutilizar Predicates como variables

Declarar los Predicate como variables (o incluso como constantes en una clase de utilidades) mejora la legibilidad y permite reutilizar la misma condición en distintos puntos del código sin duplicar lógica.

public class EmpleadoPredicates {
    public static final Predicate<Empleado> ES_DE_IT =
        e -> e.departamento().equals("IT");
}

filter() combinado con map() y collect()

List<String> nombresITConSalarioAlto = empleados.stream()
    .filter(esDeIT.and(ganaMasDe3000))
    .map(Empleado::nombre)
    .collect(Collectors.toList());

Este es el patrón más habitual en proyectos reales: filtrar según una o varias condiciones y transformar el resultado antes de recogerlo.

Errores comunes

  • Escribir condiciones muy largas dentro de una sola lambda en lugar de descomponerlas en Predicates reutilizables y legibles.
  • Olvidar que filter() no modifica la colección original, sino que produce un nuevo Stream filtrado.
  • Encadenar múltiples .filter() seguidos cuando se podría combinar todo en un único Predicate con .and(), afectando ligeramente a la legibilidad (aunque no al resultado).

Preguntas frecuentes

¿Puedo combinar más de dos Predicates? Sí, and(), or() y negate() se pueden encadenar tantas veces como sea necesario.

¿filter() modifica la lista original? No, siempre devuelve un nuevo Stream; la colección de origen permanece intacta.

¿Cuál es la diferencia entre usar varios .filter() seguidos o un solo Predicate combinado? El resultado final es el mismo, pero un único Predicate combinado con .and() suele ser más legible y reutilizable que encadenar múltiples llamadas a filter().

Siguiente paso

Dominar filter() y Predicate es el complemento natural a los conceptos generales de la API de Streams en Java.

java streams filter predicate

Newsletter Semanal de Java

Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.

🔒 Sin spam. Cancela cuando quieras.

Compartir artículo