Streams Sequência de elementos de uma fonte que suporta operações de processamento em seus dados
Streams Sequência de elementos de uma fonte que suporta operações de processamento em seus dados
Streams Uma fonte de dados para a query Uma cadeia de operações intermediárias (pipeline) Uma operação terminal que gera o resultado
Vamos a prática
public Venda( Vendedor vendedor, int ano, int valor ) { this.vendedor = vendedor; this.ano = ano; this.valor = valor; } public Vendedor( String nome, String cidade ) { this.nome = nome; this.cidade = cidade; }
Vendedor eder = new Vendedor("Eder", "Campinas"); Vendedor pedro = new Vendedor("Pedro", "Apucarana"); Vendedor luciano = new Vendedor("Luciano", "Piracicaba"); Vendedor junior = new Vendedor("Junior", "Londrina"); List<Venda> transactions = Arrays.asList( new Venda( eder, 2014, 100 ), new Venda( eder, 2013, 200 ), new Venda( pedro, 2014, 300 ), new Venda( luciano, 2012, 500 ), new Venda( luciano, 2012, 400 ), new Venda( junior, 2012, 500 ));
Quais são as vendas que fizemos em 2014? Ordenadas?
List<Venda> vendas2014 = transactions .stream()
List<Venda> vendas2014 = transactions .stream() .filter( venda -> venda.getAno() == 2014 )
List<Venda> vendas2014 = transactions .stream() .filter( venda -> venda.getAno() == 2014 ) .sorted( comparing( Venda::getValor ) )
List<Venda> vendas2014 = transactions .stream() .filter( venda -> venda.getAno() == 2014 ) .sorted( comparing( Venda::getValor ) ) .collect( toList() );
List<Venda> vendas2014 = transactions .stream() .filter( venda -> venda.getAno() == 2014 ) .sorted( comparing( Venda::getValor ) ) .collect( toList() ); vendas2014.forEach(System.out::println); Venda{vendedor=Vendedor{nome='Eder', cidade='Campinas'}, ano=2014, valor=100} Venda{vendedor=Vendedor{nome='Pedro', cidade='Apucarana'}, ano=2014, valor=300}
Em que cidades temos vendedores?
List<String> cidadesAtendidas = vendas.stream() .map( venda -> venda.getVendedor().getCidade() ) .distinct() .collect( toList() ); Campinas Apucarana Piracicaba Londrina
Qual foi a maior venda?
Optional<Integer> maiorVenda = vendas.stream() .map(Venda::getValor) .reduce( Integer::max ); maiorVenda.ifPresent( i -> System.out.println(i)); 500
Total de vendas?
Optional<Integer> totalVendas = vendas.stream() .map(Venda::getValor) .reduce( Integer::sum ); totalVendas.ifPresent( i -> System.out.println(i)); 2000
Quais são as vendas de cada vendedor? Ordenadas?
Map<Vendedor, List<Venda>> vendedorPorVendas = vendas.stream() .sorted( comparing( Venda::getValor ) ) .collect( groupingBy( Venda::getVendedor ) ); System.out.println(vendedorPorVendas); {Vendedor{nome='Junior', cidade='Londrina'}=[Venda{vendedor=Vendedor{nome='Junior', cidade='Londrina'}, ano=2012, valor=500}], Vendedor{nome='Pedro', cidade='Apucarana'}=[Venda{vendedor=Vendedor{nome='Pedro', cidade='Apucarana'}, ano=2014, valor=300}], Vendedor{nome='Luciano', cidade='Piracicaba'} =[Venda{vendedor=Vendedor{nome='Luciano', cidade='Piracicaba'}, ano=2012, valor=400}, Venda{vendedor=Vendedor{nome='Luciano', cidade='Piracicaba'}, ano=2012, valor=500}], Vendedor{nome='Eder', cidade='Campinas'}=[Venda{vendedor=Vendedor{nome='Eder', cidade='Campinas'}, ano=2014, valor=100}, Venda{vendedor=Vendedor{nome='Eder', cidade='Campinas'}, ano=2013, valor=200}]}
Streams são lazy
Stream Pipelines filter map —> collect pugs -> —> lambda lambda
Stream Pipelines intermediate intermediate —> findFirst pugs -> —> lambda lambda
Lazy Streams List<Dog> dogs = Arrays.asList( new Dog( "Dora", true, 10, Dog.RACA.PUG ), new Dog( "Bento", true, 13, Dog.RACA.PUG ), new Dog( "Rex", false, 8, Dog.RACA.SRD ), new Dog( "Teté", false, 6, Dog.RACA.SRD ), new Dog( "Banzé", true, 7, Dog.RACA.SRD ), new Dog( "Rin-Tin-Tin", false, 15, Dog.RACA.PASTOR ) );
Qual o nome do primeiro SRD que pesa mais do que 5kg?
String nomePrimeiroSRDMaiorDoQue5Kg = dogs.stream() .filter( dog -> { System.out.println( "filter - " + dog.getNome() ); return dog.getRaca().equals( Dog.RACA.SRD) && dog.getPeso() > 5; }) .map( dog -> { System.out.println( "map - " + dog.getNome() ); return dog.getNome(); }) .findFirst() .get();
Eager Streams Dora Bento Rex "Rex" —> SRD e Nome Nome Rex Teté “Teté" “Rex" —> —> —> —> —> peso> 5 Teté Banzé “Banzé" Banzé filter map findFirst Rin Tin tin
Lazy Stream Dora Bento —> SRD e Nome first() Rex “Rex" —> Rex —> —> “Rex" —> —> peso> 5 Teté Banzé filter map findFirst Rin Tin tin
String nomePrimeiroSRDMaiorDoQue5Kg = dogs.stream() .filter( dog -> { System.out.println( "filter - " + dog.getNome() ); return dog.getRaca().equals( Dog.RACA.SRD) && dog.getPeso() > 5; }) .map( dog -> { System.out.println( "map - " + dog.getNome() ); return dog.getNome(); }) .findFirst() .get(); filter - Dora List<Dog> dogs = Arrays.asList( filter - Bento new Dog( "Dora", true, 10, Dog.RACA.PUG ), new Dog( "Bento", true, 13, Dog.RACA.PUG ), filter - Rex new Dog( "Rex", false, 8, Dog.RACA.SRD ), new Dog( "Teté", false, 6, Dog.RACA.SRD ), new Dog( "Banzé", true, 7, Dog.RACA.SRD ), map - Rex new Dog( "Rin-Tin-Tin", false, 15, Dog.RACA.PASTOR ) ); Rex
Streams "infinitos"
Criar uma lista de números primos infinita
public static boolean isPrime( final int number ) { return number > 1 && IntStream.rangeClosed ( 2, (int) Math.sqrt( number ) ) . noneMatch ( divisor -> number % divisor == 0 ); } public static int primeAfter( final int number ) { if ( isPrime ( number + 1 ) ) { return number + 1; } else { return primeAfter ( number + 1 ); } }
Coleções "infinitas"
public static List<Integer> primes(final int fromNumber, final int count) { return Stream.iterate ( primeAfter(fromNumber - 1) , Primes::primeAfter ) .limit(count) .collect(Collectors.<Integer>toList()); }
public static List<Integer> primes(final int fromNumber, final int count) { return Stream.iterate ( primeAfter(fromNumber - 1) , Primes::primeAfter ) .limit(count) .collect(Collectors.<Integer>toList()); } System.out.println("10 primos do 1: " + primes( 1, 10 )); System.out.println("10 primos do 1000: " + primes( 1000, 10 )); 10 primos do 1: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] 10 primos do 1000: [1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061]
Recursões
Fibonacci
public static Long fib( int n ) { if ( n < 2 ) { return new Long( n ); } else { return fib( n - 1 ) + fib( n - 2 ); } }
Memoization
Pure Functions In computer programming, a function may be described as a pure function if both these statements about the function hold: 1-) The function always evaluates the same result value given the same argument value(s) . The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices (usually—see below. 2-) Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices (usually—see below)
Manual
Integer doubleValue(Integer x) { return x * 2; } Integer doubleValue(Integer x) { if (cache.containsKey(x)) { return cache.get(x); } else { Integer result = x * 2; cache.put(x, result) ; return result; } }
private Map<Integer, Integer> cache = new ConcurrentHashMap<>(); public Integer fib(int n) { if (n == 0 || n == 1) return n; Integer result = cache.get( n ); if (result == null) { synchronized (cache) { result = cache.get(n); if (result == null) { result = fib(n - 2) + fib(n - 1); cache.put(n, result); } } } return result; }
Java 8 to the rescue
Recommend
More recommend