Otra incorporación de Java 8 es la Streams API.
Permite junto con expresiones Lambda crear una composición de operaciones que se aplican a las colecciones. Un estilo Linq de .net pero en Java.
El procesamiento de los elementos de una colección se hace de forma declarativa. Permite manipular, realizar búsquedas y realizar conversiones en sets de datos grandes de forma eficiente.
Se componen operaciones al estilo SQL y admiten operaciones comúnmente utilizadas:
filter map, reduce, find, match, sorted…
Los patrones de procesamiento de colecciones típicos son similares a las operaciones del estilo de las que se usan en SQL para "buscar" (por ejemplo, buscar la transacción de mayor valor) o "agrupar" (por ejemplo, agrupar todas las transacciones relacionadas con compras de almacén). La mayoría de las bases de datos permiten establecer operaciones como esas de manera declarativa. Por ejemplo, la siguiente consulta de SQL permite buscar la identificación de la transacción de mayor valor: "SELECT id, MAX(value) from transactions".
Veamos un ejemplo para tener una idea del nuevo estilo de programación que posibilitan los streams de Java SE 8. Imaginemos que necesitamos encontrar todas las transacciones del tipo grocery y obtener un listado de identificaciones de transacciones ordenadas de mayor a menor por valor de transacción. En Java SE 7, usaríamos el código que se muestra aquí:
List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
if(t.getType() == Transaction.GROCERY){
groceryTransactions.add(t);
}
}
Collections.sort(groceryTransactions, new Comparator(){
public int compare(Transaction t1, Transaction t2){
return t2.getValue().compareTo(t1.getValue());
}
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
transactionsIds.add(t.getId());
}
En Java SE 8, usaremos este código :
List<Integer> transactionsIds = transactions.stream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
Un stream es como una abstracción para expresar operaciones eficientes al estilo SQL con relación a una colección de datos. Además, esas operaciones pueden parametrizarse sucintamente mediante expresiones lambda.
Además en Java SE 8 es fácil usar tareas en paralelo solo es necesario reemplazar la instrucción stream() por parallel Stream(), y la API de streams descompondrá internamente la consulta para aprovechar los núcleos múltiples de la computadora.
List<Integer> transactionsIds =
transactions.parallelStream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
Podemos entender un stream como una abstracción para expresar operaciones eficientes al estilo SQL con relación a una colección de datos. Además, esas operaciones pueden parametrizarse sucintamente mediante expresiones lambda.
Otra cosa importante es que stream es lazy es decir, no se ejecuta hasta que llamamos al metodo collect.
Dejo link:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html