O Método filter, map e flatMap
Uma transformação stream produz uma stream que tem elementos que são derivados de outros stream. A transformação filter produz uma stream com esses elementos que se combinam com uma determinada condição.
Aqui, nós transformamos uma stream de Strings dentro de outra stream que contém apenas palavras longas:
List<String> listaDePalavras = …;
Stream<String> palavrasLongas = listaDePalavras.stream().filter(w -> w.length() > 12);
O argumento filter é um Predicate<T> que é uma função de T para boolean.
Muitas vezes, você quer transformar valores de uma stream dentro de outra. Use o método map e passe a função que cuida da transformação. Por exemplo, você pode transformar todas as palavras para letras minúsculas:
Stream<String> palavrasMinusculas = listaDePalavras.stream().map(String::toLowerCase);
Aqui, nós utilizamos map como um método de referência. Muitas vezes, uma expressão lambda é utilizada:
Stream<String> primeirasLetras = listaDePalavras.stream().map(s -> s.substring(0,1));
O resultado da stream contém as primeiras letras de todas as palavras.
Quando você usa map, uma função é aplicada para cada elemento, e o resultado é uma nova stream com os resultados. Agora, suponha que você tem uma função que retorna não apenas um valor, mas uma stream de valores:
1 2 3 4 5 6 7 8 |
public static Stream<String> letras(String s){ List<String> resultado = new ArrayList<>(); for(int I = 0; I < s.length(); i++){ resultado.add(s.substring(I, i+1)); } return resultado.stream(); } |
Por exemplo, letras(“barco”) é uma stream [“b”, “a”, “r”, “c”, “o”].
Suponhamos que você utilize o map no método letras:
Stream<Stream<String>> resultado = listaDePalavras.stream().map(w -> letras(w));
Você poderá ter uma stream de streams parecida como essa […[“s”,”e”,”u”], [“b”, “a”, “r”, “c”, “o”],…].
Para transformar em uma stream de letras […”s”,”e”,”u”, “b”, “a”, “r”, “c”, “o”,…], utiliza o método flatMap ao invés de map:
Stream<String> ResultadoFlat = listaDePalavras.stream().flatMap(w -> letras(w)); //chama cada letra e nivela os resultados
Nota: você irá encontrar o método flatMap nas classes streams. É um conceito geral na ciência da computação. Suponhamos que você tem um tipo genérico G (o qual é a Stream) e funções f do tipo T para G<U> e g de U para G<V>. Então você pode compor, que primeiro aplica f e então g, utilizando flatMap. Isso é uma ideia da teoria das mônadas. Mas não se preocupe, você pode usar flatMap sem saber sobre mônadas.
Extraindo Substreams e Concatenando Streams
A chamada stream.limit(n) retorna uma nova stream que termina depois de n elementos (ou quando a stream original termina, se for curta). Esse método é particularmente útil para cortar infinitos streams até chegar ao tamanho. Por exemplo,
Stream<Double> randoms = Stream.generate(Math::random).limit(100);
Produz um fluxo de 100 números aleatórios.
A chamada stream.skip(n) faz o oposto: Descarta o primeiro n elementos. Isso é útil ao dividir texto em palavras, assim que funciona o método split, o primeiro elemento é indesejado em uma string vazia. E isso que faz o skip:
Stream<String> palavras = Stream.of(contents.split(\\PL+)).skip(1);
Você pode concatenar duas streams com o método static concat da classe Stream:
Stream<String> combinado = Stream.concat(letras(“Olá”), letras(“Mundo”)); //produz a stream [“O”,”l”,”á”,”M”,”u”,”n”,”d”,”o”]
Claro que a primeira stream não deve ser infinita, sendo que a segunda nunca terá uma chance.
Fonte: Core Java, Volume II–Advanced Features 10 edition
Deixe um comentário