O que é API de fluxo?
A API Stream é uma nova maneira de trabalhar com estruturas de dados em um estilo funcional. Uma API Stream (uma descrição das maneiras pelas quais um programa de computador pode se comunicar com outro programa) é, em sua essência, um fluxo de dados. O próprio termo "thread" é bastante vago na programação em geral e em Java em particular.List<String> list = new ArrayList<String>();
list.add("One");
list.add("Two");
list.add("Three");
list.add("Four");
list.add("Five");
list.add("Six");
list.add("Seven");
list.add("Eight");
list.add("Nine");
list.add("Ten");
Stream stream = list.stream();
Conforme mencionado acima, a API Stream permite reduzir o número de linhas de código. Exemplo com um fluxo:
IntStream.of(50, 60, 70, 80, 90, 100, 110, 120).filter(x -> x < 90).map(x -> x + 10)
.limit(3).forEach(System.out::print);
Exemplo sem thread:
int[] arr = {50, 60, 70, 80, 90, 100, 110, 120
int count = 0;
for (int x : arr) {
if (x >= 90) continue;
x += 10;
count++;
if (count > 3) break;
System.out.print(x);
}
Possíveis formas de criar um Stream:
- Fluxo vazio:
Stream.empty()
- Transmitir da lista:
list.stream()
- Transmitir do mapa:
map.entrySet().stream()
- Transmita da matriz:
Arrays.stream(array)
- Transmita a partir dos elementos especificados:
Stream.of("1", "2", "3")
- Intermediário (também chamado de “preguiçoso”) - processa os elementos recebidos e retorna o fluxo. Pode haver muitos operadores intermediários na cadeia de processamento de elementos.
- Terminal (“terminal”, também chamado de “ansioso”) - processa elementos e encerra o fluxo, portanto só pode haver um operador de terminal na cadeia.
1.List<String> list = new ArrayList<String>();
2.list.add("One");
…
11.list.add("Ten");
12.Stream stream = list.stream();
13.stream.filter(x-> x.toString().length() == 3).forEach(System.out::println);
O que está acontecendo aqui:
- 1 - crie uma lista
list
; - 2-11 - preencha com dados de teste;
- 12 - crie um objeto
Stream
; - 13 - método
filter
(filtro) - operador intermediário,x
equivale a um elemento da coleção para enumeração (como acontece comfor each
) e depois -> indicamos como nossa coleção é filtrada e como este é um operador intermediário, a coleção filtrada vai mais longe para o método ,forEach
que por sua vez é o análogo terminal (final) da enumeraçãofor each
(ExpressãoSystem.out::println
abreviada de:,x-> System.out.println(x))
que por sua vez percorre todos os elementos da coleção passada a ela e a exibe)
- O processamento não começará até que o operador do terminal seja chamado.
list.stream().filter(s -> s > 5)
(não pegará nenhum elemento da lista); - Uma instância de um fluxo não pode ser usada mais de uma vez =( ;
Portanto, toda vez que é novo:
list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println);
list.stream().forEach(x -> System.out.println(x));
Pode haver muitos operadores intermediários chamados em um fluxo, enquanto existe apenas um operador de terminal:
stream.filter(x-> x.toString().length() == 3).map(x -> x + " - the length of the letters is three").forEach(x -> System.out.println(x));
filter(Predicate predicate)
filtra o fluxo, passando apenas os elementos que passam na condição (Predicate é uma interface funcional integrada adicionada ao pacote no Java SE 8.java.util.function
Verifica o valor para “ true ” e “ false ”);map(Function mapper)
torna possível criar uma função com a qual iremos alterar cada elemento e ignorá-lo ainda mais (A interface funcionalFunction<T,R>
representa a função de transição de um objeto do tipo T para um objeto do tipo R)flatMap(Function<T, Stream<R>> mapper)
- como no caso demap
, eles são usados para converter em um fluxo primitivo.
[stream1,stream2,stream3,stream4] => stream
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.flatMap(Arrays::stream).distinct() //aligns each generated thread into a single thread
.collect(Collectors.toList()).forEach(System.out::println);
Embora map
seja convertido em uma lista de threads (mais precisamente <Stream>
threads) [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4)
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.map(Arrays::stream).distinct() //Make the array into a separate thread
.collect(Collectors.toList()).forEach(System.out::println);
Outra diferença em relação ao map
, você pode converter um elemento em zero, um ou muitos outros. Para converter um elemento em zero elementos, você precisa retornar null
ou um fluxo vazio. Para converter para um elemento, você precisa retornar um fluxo de um elemento, por exemplo, via Stream.of(x)
. Para retornar vários elementos, você pode criar um stream com esses elementos por qualquer meio. O mesmo método flatMap, mas para Double, Integer e Long:
- flatMapToDouble (mapeador de função)
- flatMapToInt (mapeador de função)
- flatMapToLong (mapeador de função)
Stream.of(2, 3, 0, 1, 3)
.flatMapToInt(x -> IntStream.range(0, x))
.forEach(System.out::print);// 010120012
-
IntStream.range(0,x) – gera elementos de 0 (inclusivo) a x (não inclusivo) para o fluxo;
mapa:
Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//list of streams (streams);
-
limit(long maxSize) – limita o fluxo pelo número de elementos:
stream.limit(5).forEach(x -> System.out.println(x));
-
pular (n longo) – pular n elementos:
stream.skip(3).forEach(x -> System.out.println(x));
-
classificado()
- sorted(Comparator comparator) – classifica o fluxo (classificando como TreeMap):
stream.sorted().forEach(x -> System.out.println(x));
-
distinto() — verifica o fluxo quanto à exclusividade dos elementos (remove repetições de elementos);
-
dropWhile(Predicate predicate) - ignora elementos que satisfazem a condição (apareceu em java 9, a interface funcional Predicate<T> verifica se uma determinada condição é atendida. Se for atendida, então true é retornado. A expressão lambda leva um objeto de digite T como parâmetro:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach(Consumer action) – análogo a for each (Consumer<T> executa alguma ação em um objeto do tipo T sem retornar nada);
-
count() – retorna o número de elementos do fluxo:
System.out.println(stream.count());
-
coletar(Coletor coletor) – método coleta todos os elementos em uma lista, conjunto ou outra coleção, agrupa elementos de acordo com algum critério, combina tudo em uma string, etc.:
List<String> list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList());
-
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
— o mesmo que ,collect(collector)
apenas os parâmetros são divididos por conveniência (supplier
fornece novos objetos (contêineres), por exemplonew ArrayList()
,accumulator
adiciona um elemento ao contêiner,combiner
combina partes do fluxo); -
reduzir (identidade T, acumulador BinaryOperator) - converte todos os elementos do fluxo em um objeto (calcula a soma de todos os elementos ou encontra o elemento mínimo), primeiro pega o objeto
identity
e o primeiro elemento do fluxo, aplica a funçãoaccumulator
eidentity
torna-se seu resultado. Então tudo continua para os elementos restantes.int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25
-
reduce(BinaryOperator accumulator)
- o mesmo método acima, mas falta o inicialidentity
, é o primeiro elemento do fluxoOptional min(Comparator comparator)
Opcional max(Comparator comparator) procura o elemento mínimo/máximo com base no comparador passado; -
findFirst()
– extrai o primeiro elemento do fluxo:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
— retorna verdadeiro se todos os elementos do fluxo satisfizerem a condição. Se for encontrado qualquer elemento cujo resultado da chamada da função de predicado seja false , o operador para de verificar os elementos e retorna false :Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
-
anyMatch(Predicate predicate)
— retornará verdadeiro se pelo menos um elemento do fluxo satisfizer a condiçãopredicate
:Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
-
noneMatch(Predicate predicate)
— retornará verdadeiro se, tendo passado por todos os elementos do fluxo, nenhum deles satisfez a condiçãopredicate
:Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
Collectors
:
-
toList()
— coleta elementos emList
:List<Integer> list = Stream.of(99, 2, 3).collect(Collectors.toList());
-
toSet()
— coleta elementos em um conjunto:Set<Integer> set = Stream.of(99, 2, 3).collect(Collectors.toSet());
-
counting()
— Conta o número de elementos:Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting());
-
joining()
-
joining(CharSequence delimiter)
-
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
— coleta elementos em uma linha. Além disso, você pode especificar um separador, bem como um prefixo e um sufixo para toda a sequência:String a = Stream.of("s", "u" ,"p", "e", "r").collect(Collectors.joining()); System.out.println(a); // super String b = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining("-")); System.out.println(b); // s-u-p-e-r String c = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining(" -> ", "[ ", " ]")); System.out.println(c); // [ s -> u -> p -> e -> r ]
-
summingInt(ToIntFunction mapper)
-
summingLong(ToLongFunction mapper)
-
summingDouble(ToDoubleFunction mapper)
- um coletor que converte objetos em int/long/double e calcula a soma.
GO TO FULL VERSION