Java 8 Uso de Stream básico

Podemos definir Streams como una secuencia de funciones que se ejecutan una detrás de otra, de forma anidada.

Comparemos antes un Iterador con un Stream. Habitualmente cuando tenemos una collection lo que hacemos luego es iterar para realizar algo con dicha colección.

Un Stream luce similar a una collection permitiendo además realizar operaciones directamente sobre el Stream. Cada operación devuelve un nuevo stream sobre el cual podemos seguir encadenando otras operaciones.

String einstein = "La imaginación es más importante que el conocimiento";
        String[] splited = einstein.split("\\s+");

        // Collection to Iterate
        List<String> words = Arrays.asList(splited);

        int count = 0;
        for(String w : words) {
            if(w.startsWith("i")) {
                count++;
            }
        }

        // JAVA 8
        words.stream().filter(w -> w.startsWith("i")).count();

Las operaciones sobre Stream pueden ser intermedias o finales. En el caso de ser intermedias (filter, sorted, map) stream devolverá nuevamente otro stream permitiendo la continuidad de pasos o funciones sobre ella misma. Esto es llamado ‘pipelining’.

In computing, a pipeline is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time-sliced fashion; in that case, some amount of buffer storage is often inserted between elements.

Wikipedia

Estas son algunas funciones intermedias:

// Intermediate operations
        Stream<Product> stream = products.stream();
        Stream<Product> filterStream = stream.filter(p -> "B".equals(p.getType()));
        Stream<Product> sorted = filterStream.sorted(comparing(Product::getPrice));

        // Final operation
        sorted.forEach(System.out::println);

Si no has leido sobre Lamndas te recomiendo una breve lectura antes.

Supongamos que quieres procesar una lista de productos y realizar diferentes procesos como:

  • recorrer la lista
  • filtrar durante el recorrido los elementos según alguna condición
  • ordenar el resultado anterior
  • mostrar el resultado

Harías estas operaciones de forma tradicional así:

List<Product> products = getProducts();
        List<Product> resultFilter = new ArrayList<>();

        // foreach filter
        for(Product p : products) {
            if("B".equals(p.getType())){
                resultFilter.add(p);
            }
        }
        // sort
        Collections.sort(resultFilter, new Comparator<Product>() {
            @Override
            public int compare(Product p1, Product p2) {
                return p1.getPrice().compareTo(p2.getPrice());
            }
        });
        // print
        for(Product p: resultFilter) {
            System.out.println(p);
        }  

La clase Product que usas es:

public class Product {

    private long id;
    private String name;
    private String type;
    private Double price;

    // get and set...
}

Como usar Stream con Java 8

Con Java 8 utilizando Streams y Lambdas haces las mismas operaciones anteriores de este modo:

List<Product> products = getProducts();

        // filter + sort + print
        products.stream().filter(p ->"B".equals(p.getType())).
                sorted(comparing(Product::getPrice)).
                forEach(System.out::println);

Puedes observar rápidamente la reducción en líneas de código y complejidad con este simple ejemplo.

Ejemplos de uso simple Stream con Java 8

Observa esta operaciones usando Stream y como pueden ayudarte

List<Product> products = getProducts();

        // limit and foreach
        products.stream().limit(10).forEach(System.out::println);

        // filter and count
        long count = products.stream().filter(product -> product.getPrice() > 200d).count();
        System.out.println(count);

        // collect ids
        List<Long> ids = products.stream().filter(product -> product.getPrice() > 200d).
                map(p -> p.getId()).collect(Collectors.toList());
        ids.forEach(System.out::print);  // print this ids..

        //statistics
        DoubleSummaryStatistics doubleSummaryStatistics = products.stream().mapToDouble(p -> p.getPrice()).summaryStatistics();
        System.out.println(doubleSummaryStatistics.getSum());
        System.out.println(doubleSummaryStatistics.getMax());
        System.out.println(doubleSummaryStatistics.getMin());

Referencias: [http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html]3

Descarga este código completo

Hi! If you find my posts helpful, please support me by inviting me for a coffee :)

Ver también