JavaRush /Blogue Java /Random-PT /API de fluxo

API de fluxo

Publicado no grupo Random-PT
API de fluxo - 1

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.
API de fluxo - 1
Com o advento do Java 8, a API Stream permitiu aos programadores escrever de forma muito mais breve o que antes exigia muitas linhas de código, nomeadamente, para simplificar o trabalho com conjuntos de dados, em particular, para simplificar a filtragem, classificação e outras operações de manipulação de dados. Se você não possui operações intermediárias, muitas vezes você pode e deve fazer isso sem um fluxo, caso contrário o código será mais complicado do que sem um fluxo.
API de fluxo - 2
Por onde, exatamente, devo começar? A partir da criação de uma instância Stream, que é baseada na coleção, array ou método que precisamos e de onde os dados serão retirados de acordo:
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:
API de fluxo - 3
  • 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")
Além disso, existem operadores (essencialmente métodos da classe Stream) Os operadores podem ser divididos em dois grupos:
  • 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.
Exemplo:
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, xequivale a um elemento da coleção para enumeração (como acontece com for 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 , forEachque por sua vez é o análogo terminal (final) da enumeração for each(Expressão System.out::printlnabreviada de:, x-> System.out.println(x))que por sua vez percorre todos os elementos da coleção passada a ela e a exibe)
API de fluxo - 5
Pontos importantes:
  • 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 =( ;
  • API de fluxo - 6

    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));
A seguir, vejamos alguns operadores intermediários:
API de fluxo - 7
  • 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.functionVerifica 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 funcional Function<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 de map, eles são usados ​​para converter em um fluxo primitivo.
Ao trabalhar, por exemplo, com uma matriz de fluxos (matrizes, listas e assim por diante), ele os converte em um único fluxo (matriz, lista e assim por diante [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 mapseja 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 nullou 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)
E outro exemplo para comparação, flatMap:
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
Operadores de terminal:
API de fluxo - 8
  • 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 ( supplierfornece novos objetos (contêineres), por exemplo new ArrayList(), accumulatoradiciona um elemento ao contêiner, combinercombina 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 identitye o primeiro elemento do fluxo, aplica a função accumulatore identitytorna-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 inicial identity, é o primeiro elemento do fluxo

    Optional 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ção predicate:

    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ção predicate:

    Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
E, finalmente, gostaria de examinar alguns métodos Collectors:
  • toList()— coleta elementos em List:

    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.

Links Úteis: PS: não tenha vergonha de nos dar likes ^ : ^
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION