JavaRush /Blog Java /Random-ES /API de transmisión

API de transmisión

Publicado en el grupo Random-ES
API de transmisión - 1

¿Qué es Stream API?

Stream API es una nueva forma de trabajar con estructuras de datos en un estilo funcional. Una Stream API (una descripción de las formas en que un programa informático puede comunicarse con otro programa) es, en esencia, un flujo de datos. El término "hilo" en sí es bastante vago en programación en general y en Java en particular.
API de transmisión - 1
Con la llegada de Java 8, Stream API permitió a los programadores escribir mucho más brevemente lo que antes requería muchas líneas de código, es decir, simplificar el trabajo con conjuntos de datos, en particular, simplificar el filtrado, la clasificación y otras operaciones de manipulación de datos. Si no tiene operaciones intermedias, a menudo puede y debe prescindir de una secuencia; de lo contrario, el código será más complicado que sin una secuencia.
API de transmisión - 2
¿Por dónde debería empezar exactamente? Desde la creación de una instancia de Stream, la cual se basa en la colección, array o método que necesitamos y de donde se tomarán los datos en consecuencia:
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();
Como se mencionó anteriormente, Stream API le permite reducir la cantidad de líneas de código. Ejemplo con una secuencia:
IntStream.of(50, 60, 70, 80, 90, 100, 110, 120).filter(x -> x < 90).map(x -> x + 10)
.limit(3).forEach(System.out::print);
Ejemplo sin hilo:
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);
	}
Posibles formas de crear una transmisión:
API de transmisión - 3
  • Flujo vacío:Stream.empty()
  • Transmitir desde la lista:list.stream()
  • Transmitir desde el mapa:map.entrySet().stream()
  • Transmitir desde la matriz:Arrays.stream(array)
  • Transmitir desde los elementos especificados:Stream.of("1", "2", "3")
A continuación, existen los operadores (esencialmente métodos de la clase Stream), que se pueden dividir en dos grupos:
  • Intermedio (también llamado "perezoso"): procesa los elementos entrantes y devuelve la secuencia. Puede haber muchos operadores intermedios en la cadena de procesamiento de elementos.
  • Terminal ("terminal", también llamado "ansioso"): procesa elementos y finaliza la secuencia, por lo que solo puede haber un operador de terminal en la cadena.
Ejemplo:
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);
Que está pasando aqui:
  • 1 - crear una lista list;
  • 2-11 - llénelo con datos de prueba;
  • 12 - crear un objeto Stream;
  • 13 - método filter(filtro) - operador intermedio, xequivale a un elemento de la colección para enumeración (como con for each) y después -> indicamos cómo se filtra nuestra colección y como este es un operador intermedio, la colección filtrada va más allá del método , forEachque a su vez es el análogo terminal (final) de la enumeración for each(expresión System.out::printlnabreviada de:, x-> System.out.println(x))que a su vez revisa todos los elementos de la colección que se le pasan y los muestra)
API de transmisión - 5
Puntos importantes:
  • El procesamiento no comenzará hasta que se llame al operador de la terminal. list.stream().filter(s -> s > 5)(no tomará ni un solo elemento de la lista);
  • Una instancia de una secuencia no se puede utilizar más de una vez =( ;
  • API de transmisión - 6

    Por eso, cada vez que sea nuevo:

    list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println);
    list.stream().forEach(x -> System.out.println(x));
  • Puede haber muchos operadores intermedios llamados en una secuencia, mientras que solo hay un 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 continuación, veamos algunos operadores intermedios:
API de transmisión - 7
  • filter(Predicate predicate)filtra la secuencia, pasando solo aquellos elementos que pasan la condición (El predicado es una interfaz funcional incorporada agregada al paquete en Java SE 8. java.util.functionComprueba el valor de " verdadero " y " falso ");
  • map(Function mapper)permite crear una función con la que cambiaremos cada elemento y lo omitiremos más (la interfaz funcional Function<T,R>representa la función de transición de un objeto de tipo T a un objeto de tipo R)
  • flatMap(Function<T, Stream<R>> mapper)- como en el caso de map, se utilizan para convertir a una secuencia primitiva.
Cuando se trabaja, por ejemplo, con una matriz de secuencias (matrices, listas, etc.), las convierte en una secuencia (matriz, lista, etc.) [stream1,stream2,stream3,stream4] => stream:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convierte la palabra en una matriz de letras
        .flatMap(Arrays::stream).distinct() //alinea cada subproceso generado en un solo subproceso
        .collect(Collectors.toList()).forEach(System.out::println);
Mientras mapse convierte en una lista de subprocesos (más precisamente <Stream>subprocesos) [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("")) //Convierte la palabra en una matriz de letras
        .map(Arrays::stream).distinct() //Hacer la matriz en un hilo separado
        .collect(Collectors.toList()).forEach(System.out::println);
Otra diferencia con respecto a map, puedes convertir un elemento en cero, uno o muchos otros. Para convertir un elemento en cero elementos, debe devolver nullo una secuencia vacía. Para convertir a un elemento, debe devolver una secuencia de un elemento, por ejemplo, a través de Stream.of(x). Para devolver varios elementos, puedes crear una secuencia con estos elementos por cualquier medio. Mismo método flatMap, pero para Double, Integer y Long:
  • flatMapToDouble (asignador de funciones)
  • flatMapToInt (asignador de funciones)
  • flatMapToLong (asignador de funciones)
Y otro ejemplo a modo de comparación, flatMap:
Stream.of(2, 3, 0, 1, 3)
        .flatMapToInt(x -> IntStream.range(0, x))
        .forEach(System.out::print);// 010120012
  • IntStream.range(0,x): genera elementos de 0 (inclusive) ax (no inclusivo) a la secuencia;

    mapa:

    Stream.of(2, 3, 0, 1, 3)
            .map(x -> IntStream.range(0, x))
            .forEach(System.out::print);//lista de flujos (streams);
  • limit(long maxSize): limita la secuencia por el número de elementos:

    stream.limit(5).forEach(x -> System.out.println(x));
  • skip(long n) – salta n elementos:

    stream.skip(3).forEach(x -> System.out.println(x));
  • ordenado()

  • ordenado(Comparador comparador): ordena la secuencia (ordenando como TreeMap):

    stream.sorted().forEach(x -> System.out.println(x));
  • distintivo() — comprueba la unicidad de los elementos en la secuencia (elimina las repeticiones de elementos);

  • dropWhile(Predicate predicate): omite elementos que satisfacen la condición (apareció en Java 9. La interfaz funcional Predicate<T> verifica si se cumple una determinada condición. Si se cumple, se devuelve verdadero. La expresión lambda toma un objeto de escriba 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 terminales:
API de transmisión - 8
  • forEach(Acción del consumidor): análogo a para cada (El consumidor<T> realiza alguna acción en un objeto de tipo T sin devolver nada);

  • count() – devuelve el número de elementos de la secuencia:

    System.out.println(stream.count());

  • recopilar(Recolector recopilador): el método recopila todos los elementos en una lista, conjunto u otra colección, agrupa elementos según algún criterio, combina todo en una cadena, etc.:

    List<String> list = Stream.of(One,Two,Three).collect(Collectors.toList());
  • collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)— lo mismo que , collect(collector)solo que los parámetros se desglosan por conveniencia ( suppliersuministra nuevos objetos (contenedores), por ejemplo new ArrayList(), accumulatoragrega un elemento al contenedor, combinercombina partes del flujo);

  • reduce(T identidad, acumulador BinaryOperator): convierte todos los elementos de la secuencia en un objeto (calcula la suma de todos los elementos o encuentra el elemento mínimo), primero se identitytoman el objeto y el primer elemento de la secuencia, se aplica la función accumulatory identitysu resultado se convierte en. Luego todo continúa con los elementos restantes.

    int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25
  • reduce(BinaryOperator accumulator)- el mismo método que el anterior pero falta el inicial identity, es el primer elemento de la secuencia

    Optional min(Comparator comparator)
    Opcional max(Comparator comparador) busca el elemento mínimo/máximo según el comparador pasado;

  • findFirst()– saca el primer elemento de la secuencia:

    Stream.of(1, 2, 3, 4, 9).findFirst();
  • allMatch(Predicate predicate)— devuelve verdadero si todos los elementos de la secuencia cumplen la condición. Si se encuentra algún elemento cuyo resultado de llamar a la función de predicado es falso , entonces el operador deja de escanear los elementos y devuelve falso :

    Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
  • anyMatch(Predicate predicate)— devolverá verdadero si al menos un elemento de la secuencia satisface la condición predicate:

    Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
  • noneMatch(Predicate predicate)— devolverá verdadero si, habiendo pasado por todos los elementos de la secuencia, ninguno de ellos cumplió la condición predicate:

    Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
Y finalmente me gustaría ver algunos métodos Collectors:
  • toList()- recopila elementos en List:

    List<Integer> list = Stream.of(99, 2, 3).collect(Collectors.toList());
  • toSet()— reúne elementos en un conjunto:

    Set<Integer> set = Stream.of(99, 2, 3).collect(Collectors.toSet());
  • counting()— Cuenta el 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)— reúne elementos en una línea. Además, puedes especificar un separador, así como un prefijo y un sufijo para toda la secuencia:

    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)- un recopilador que convierte objetos a int/long/double y calcula la suma.

Enlaces útiles: PD: no tengas vergüenza de colmarnos de me gusta ^ : ^
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION