API STREAM &
OPTIONALS
P R O G R A M A C I Ó N 3
P R O F . M A N G O E D U A R D O
CONTENIDO
01 API Stream
02 Operaciones intermedias
03 Operaciones terminales
04 Parallel Streams
05 Optional <T>
API Stream
Un Stream en Java es una secuencia de elementos que admite
operaciones funcionales, como filtrado, mapeo y reducción. No
es una estructura de datos, sino una abstracción para procesar
datos de manera eficiente.
Características principales
Inmutabilidad: No modifican la fuente de datos, sino que
generan nuevos Streams con los resultados.
Lazy Evaluation: Las operaciones intermedias no se
ejecutan hasta que se encuentra una operación terminal.
Uso de pipelines: Las operaciones se encadenan en un flujo
de ejecución claro y conciso.
Stream Pipeline
Desde una colección
List<String> nombres = [Link]("Juan", "Ana", "Luis");
Stream<String> streamDesdeLista = [Link]();
Desde un arreglo
Creación de un String[] nombresArray = {"Carlos", "María", "José"};
Stream Stream<String> stream = [Link](nombresArray);
Desde valores especificos
Stream<Integer> stream = [Link](1, 2, 3, 4, 5);
Desde un generador infinito
Stream<Double> streamAleatorio =
[Link](Math::random).limit(5);
Des
Operaciones intermedias
filter(Predicate<T>) → Filtra los elementos según una condición.
map(Function<T, R>) → Transforma los elementos del Stream.
flatMap(Function<T, Stream<R>>) → Aplana estructuras anidadas en un solo
Stream.
distinct( ) → Elimina duplicados.
sorted(Comparator<T>) / sorted( ) → Ordena los elementos.
limit(long maxSize) → Limita el número de elementos en el stream a un tamaño
máximo especificado.
peek(Consumer<T>) → Permite inspeccionar los elementos sin modificarlos.
skip(long n) → Descarta los primeros n elementos del stream
Ejemplos
.filter ( )
.map( )
Ejemplos
.flatMap( )
Ejemplos
.distinct ( ) & .sorted ( )
.limit ( ) & .peek ( )
¿Que se mostrará por consola?
Ejemplos
.skip ( )
Las operaciones terminales son aquellas que
producen un resultado o efecto secundario,
marcando el final de un flujo de datos. A diferencia
Operaciones de las operaciones intermedias, que transforman
un flujo en otro, las operaciones terminales
terminales consumen el flujo y producen un resultado final.
Características clave:
Producen un resultado
Finalizan el flujo
Operaciones terminales
collect([Link]()) → Convierte un Stream en una colección.
forEach(Consumer<T>) → Itera sobre cada elemento.
count() → Cuenta la cantidad de elementos.
reduce(BinaryOperator<T>) → Combina los elementos en un solo valor.
anyMatch/allMatch/noneMatch (Predicate<T>) → Devuelve True si alguno, todos
o ninguno de los elementos cumplen una condición.
findFirst() → Devuelve el primer elemento, si es que existe.
min / max (Comparator<T>) → Devuelve el elemento mínimo o máximo del flujo,
según el Comparator dado.
.reduce( ) & .max( )
Parallel Streams
Uno de los aspectos más importantes de la API Stream es su
capacidad de procesar datos en paralelo mediante
parallelStream() o parallel(). Esto permite aprovechar múltiples
núcleos de la CPU para mejorar el rendimiento
Por defecto, los Streams son secuenciales, ejecutando las
operaciones en un solo hilo. Si se usa parallelStream(), Java los
divide en múltiples tareas que se ejecutan en diferentes hilos.
¿Cuándo utilizar parallelStream( )?
✅ Casos recomendados:
Se procesan grandes cantidades de datos.
Las operaciones son independientes entre sí.
Se tienen múltiples núcleos disponibles.
Las operaciones dentro del Stream no son bloqueantes.
❌ Casos donde NO es recomendable:
Se trabaja con colecciones pequeñas
Se accede a recursos compartidos, como archivos o bases de datos.
Se tiene un alto costo en la creación de hilos.
Si el orden de los resultados es importante
NullPointerException
Optional<T>
En Java, Optional<T> es una clase genérica introducida en Java
8 dentro del paquete [Link]. Su propósito principal es
representar valores que pueden estar presentes o ausentes,
evitando así el uso de null y reduciendo el riesgo de
excepciones como NullPointerException.
Es decir, es un envoltorio que puede contener el valor, o nulo.
Desde un valor no nulo
Optional<String> nombre = [Link](“Pedro”);
Creación de un Desde un valor que puede ser nulo
Optional < T > Optional<String> nombre = [Link](“Pedro”);
Optional<String> nombre = [Link](null);
Crear un Optional vacio
Optional<String> nombre = [Link]( );
Des
Verificar si contiene un valor
Verificación de .isEmpty ( ) - Devuelve True si esta vacio
valores en .isPresent ( ) - Devuelve True si tiene un valor
Optional < T > .ifPresent(Consumer<T>) - Ejecuta una acción si esta
presente
Des
Obtener el valor
.get( ) - Devuelve el valor. Si no existe, lanza
NoSuchElementException. No recomendado
Obtener el valor .orElse(T defecto ) - Devuelve el valor si existe o el defecto si
de un no existe.
.orElseGet(Supplier<T>) - Devuelve el valor si existe o ejecuta
Optional < T > el Supplier si está vacío.
.orElseThrow(Supplier<Throwable>) - Devuelve el valor o
lanza una excepción personalizada si el Optional está vacío.
Des
Transformar el valor
.map(Function<T, R> - Transforma el valor contenido si está
presente.
.flatMap(Function<T, Optional<R>>) - Similar a map, pero
Transformaciones evita anidaciones de Optional.
y filtrados con Filtrado
.filter(Predicate<T>) - Filtra el valor contenido según una
Optional < T > condición.
.stream( ) - Convierte un Optional<T> en un Stream<T> que
contiene un solo elemento si el Optional tiene un valor, o un
Stream vacío si el Optional está vacío.
Des
¿Cuándo utilizar Optional<T>?
✅ Casos recomendados:
Como parametro de retorno cuando se puede devolver null.
❌ Casos donde NO es recomendable:
Como parametro de un metodo. (Usar [Link]( ))
Como atributo de una clase. (Usar valores por defecto o validaciones)
Evitar Optional anidados como Optional<List<T>> - Usar colecciones vacias.
API STREAM &
OPTIONAL <T>
P R O G R A M A C I Ó N 3
P R O F . M A N G O E D U A R D O
Universidad Tecnológica Nacional de Mar del Plata