Flujo en Java 8 - Conceptos de codificación N

Una de las principales características de Java 8 es la incorporación de Stream. También introdujo la programación funcional en Java. Discutiremos diferentes operaciones de flujo disponibles en Collection, Array, IntStream con ejemplos. También discutiremos la diferencia entre operaciones intermedias y terminales.

Índice
  1. Operaciones de flujo
  2. Listado.Arroyo()
  3. Listado.Arroyo()
  4. IntStream.of() | .intervalo()
  5. Array.stream()

Operaciones de flujo


Hay principalmente tres partes de cualquier operación de flujo: -

1. Crea un flujo

Estos son llamados como Operación de flujoque crea una secuencia a partir de un rango o colección determinada.

List<String>.stream(), List<Object>.stream(), Arrays.stream(), IntStream.of(), IntStream.range()

2. Procesar la transmisión

Estos son llamados como Operación intermedia, que convierte un flujo en otro flujo en consecuencia. Se pueden encadenar para formar una canalización de operaciones de Stream.

filter(), map(), flatMap(), sorted(), distinct(), limit(), skip()

3. Consumir el pienso

Estos son llamados como Operación de terminales, que convierte una secuencia en un resultado, una colección o un vacío. No se pueden encadenar. Cualquier canalización de operación de Stream debe terminar con una operación de terminal.

forEach(), collect(), reduce(), min(), max(), count(), average(), sum(), anyMatch(), allMatch(), noneMatch(), findFirst(), findAny()

1. Salida: La salida de la operación intermedia es otra secuencia, mientras que la salida de la operación terminal es una colección, una matriz o una primitiva.

2. Encadenamiento: La tubería de operación de flujo puede tener cualquier número de operadores intermedios encadenados, pero la tubería debe terminar con el operador terminal.

3. Evaluación perezosa: Las operaciones intermedias se evalúan con pereza, mientras que las operaciones terminales son codiciosas. Las operaciones intermedias permanecen como una canalización y se ejecutan solo cuando se ejecuta la operación terminal

4. Tubería: La canalización de operaciones de flujo puede tener muchas operaciones intermedias, pero solo una operación terminal.

Listado.Arroyo()

Veremos varias canalizaciones de operaciones de flujo. Definamos un fruits Listar la colección primero

List<String> fruits = Arrays.asList("mango", "apple", "banana", "grapes", "orange");

Ahora estamos ejecutando varios ejemplos de canalización de operaciones de transmisión

Stream Operation | Intermediate Operation | ... | ... | Intermediate Operation | Terminal Operation

Ejemplo 1. Filtrar elementos de la lista
stream() | filter() | collect()

Filtrar todo excepto grapes de la lista fruits

List<String> result = fruits.stream()                   // convert list to stream
            .filter(fruit -> !"grapes".equals(fruit))   // filter out grapes
            .collect(Collectors.toList());              // collect the output and convert streams to a List

result.forEach(System.out::println);

Output

mango apple banana orange

Ejemplo 2. Modificar todos los elementos de la lista
stream() | map() | collect()

Asignar todos los elementos de la lista fruits en mayúscula

List<String> result = fruits.stream()            // convert list to stream
            .map(fruit -> fruit.toUpperCase())   // map to uppercase
            .collect(Collectors.toList());       // collect the output and convert streams to a List

result.forEach(System.out::println);

Output

MANGO APPLE BANANA GRAPES ORANGE

Ejemplo 3. Ordenar todos los elementos de la lista
stream() | sorted() | collect()

Ordenar todos los elementos de la Lista fruits en orden alfabético

List<String> result = fruits.stream()        // convert list to stream
            .sorted()                        // sort in alphabetical order
            .collect(Collectors.toList());   // collect the output and convert streams to a List

result.forEach(System.out::println);

Output

apple banana grapes mango orange

Ejemplo 4. Varias operaciones intermedias
stream() | filter() | map() | sorted() | collect()

Procesamiento de secuencias múltiples de Lista fruits. Filtrar todo excepto grapesMapéalos en mayúsculas, ordénalos alfabéticamente.

List<String> result = fruits.stream()                   // convert list to stream
            .filter(fruit -> !"grapes".equals(fruit))   // filter out grapes
            .map(fruit -> fruit.toUpperCase())          // map to uppercase
            .sorted()                                   // sort in alphabetical order
            .collect(Collectors.toList());              // collect the output and convert streams to a List

result.forEach(System.out::println);

Output

APPLE BANANA MANGO ORANGE

Ejemplo 5. Buscar elementos en la lista
stream() | filter() | findAny() | orElse()

Filtrado mango de la lista fruitsDevolver a mango si se encuentra o de lo contrario volver null

String fruit = fruits.stream()                         // convert list to stream
            .filter(fruit -> "mango".equals(fruit))    // we love mango
            .findAny()                                 // If `findAny` then return found
            .orElse(null);                             // If not found, return null

System.out.println(fruit);

Output

mango

Listado.Arroyo()


Los flujos también funcionan con objetos.

Ejemplo 1. Encuentra los 3 empleados mejor pagados

Primero hagámoslo de la manera habitual: -

List<Employee> employees = getAllEmployees();

// Copy to new list to avoid mutating original array
List<Employee> copy = new ArrayList<>(employees);

// Sort descending
copy.sort((o1, o2) -> o2.getSalary() - o1.getSalary());

// Get first 3
for(int i=0; i<3; i++){
  Employee employee = copy.get(i);
  System.out.println(employee.getName());
}

Ahora use secuencias para hacer lo mismo: -

List<Employee> employees = getAllEmployees();
employees.stream()
         .sorted(Comparator.comparingInt(Employee::getSalary).reversed())
         .limit(3)
         .map(Employee::getName)
         .forEach(System.out::println)

Ejemplo 2. Lista de recopiladores (operaciones de cola)

Veamos varios colectores (operaciones terminales) disponibles: -

List<Employee> employees = getAllEmployees();

// to list
List<String> listOfEmps = employees.stream()
         .limit(3)
         .map(Employee::getName)
         .collect(Collectors.toList());

// to set
Set<String> setOfEmps = employees.stream()
         .limit(3)
         .map(Employee::getName)
         .collect(Collectors.toSet());

// to map
Map<String, Employee> mapOfEmps = employees.stream()
         .limit(3)
         .collect(Collectors.toMap(e -> e.name, e -> e));

// john, amy, marcy
String names = employees.stream()
         .limit(3)
         .map(Employee::getName)
         .collect(Collectors.joining(","));

// group by dept
Map<String, List<Employee>> empByDept 
          = employees.stream()
         .collect(Collectors.groupingBy(e -> e.dept));

// count employees in each dept
Map<String, Long> countByDept 
          = employees.stream()
         .collect(Collectors.groupingBy(Employee::getDept, Collectors.counting()));

Ejemplo 3. Operaciones en paralelo

Las operaciones de transmisión se ejecutan secuencialmente de forma predeterminada. Puede iniciar operaciones de flujo paralelo usando .parallel() transacción. Se recomienda usar la operación en paralelo solo cuando la Lista es considerablemente grande, de lo contrario, habrá un impacto en el rendimiento.

// parallel stream
Map<String, List<Employee>> empMapByDept 
          = employees.stream()
          .parallel()
          .collect(Collectors.groupingBy(e -> e.dept));

IntStream.of() | .intervalo()


Ejemplo 1. Ejecutar un ciclo for de 1 a n-1
int n = 6;
IntStream.range(1, n)
         .forEach(System.out::println);

Output

1 2 3 4 5

Ejemplo 2. Obtenga min, max, avg, count y sum de una matriz dada

Encuentre el mínimo de una matriz dada de números: -

int[] nums = {4, 1, 13, 90, 16, 2, 0};
int min = IntStream.of(nums)   //create stream
          .min()
          .getAsInt();

System.out.println("min: " + min);

Output

min: 0

getAsInt() lanzar una excepción si no se encuentra min, por ejemplo, si la matriz está vacía. Un método alternativo es ifPresent()

IntStream.of(new int[0])
         .min()
         .ifPresent(min -> System.out.println(min));
// OR
IntStream.of(new int[0])
         .min()
         .ifPresent(System.out::println);

Cambiamos la expresión lambda min -> System.out.println(min) doble colon System.out::println en una versión posterior. Ambos hacen lo mismo.

Otras operaciones estadísticas similares son: -

int[] nums = {4, 1, 13, 90, 16, 2, 0};
int min    = IntStream.of(nums).min().getAsInt();
int max    = IntStream.of(nums).max().getAsInt();
double avg = IntStream.of(nums).average().getAsDouble();
long count = IntStream.of(nums).count();
long sum   = IntStream.of(nums).sum();

Alternativamente, puede crear un feed solo una vez para obtener todas las estadísticas:

IntSummaryStatistics stats = IntStream.of(nums).summaryStatistics();
int min    = stats.getMin();
int max    = stats.getMax();
double avg = stats.getAverage();
long count = stats.getCount();
long sum   = stats.getSum();

Ejemplo 3. Encuentra los 3 números distintos más pequeños de una matriz dada
int[] nums = {4, 1, 13, 90, 16, 2, 0};
IntStream.of(nums)
         .distinct()
         .sorted()
         .limit(3)
         .forEach(System.out::println);

Output

0 1 2

Tenga en cuenta que los flujos operan en la copia de la matriz y no modifican la matriz original.

Puede modificar la (última) operación de terminal, por ejemplo, si queremos la suma de 3 números pequeños distintos: -

int[] nums = {4, 1, 13, 90, 16, 2, 0};
long sum = IntStream.of(nums)
         .distinct()
         .sorted()
         .limit(3)
         .sum();

Ejemplo 4. Todas las operaciones posibles en IntStream
crear una corriente
IntStream.of(numbers);           // from Array
IntStream.range(1, 101);         // 1..100
IntStream.rangeClosed(1, 100);   // 1..100
IntStream.generate(supplier());  // from supplier
Flujo de proceso
IntStream.of(numbers).distinct();           // distinct
IntStream.of(numbers).sorted();             // sort
IntStream.of(numbers).limit(3);             // get first 3
IntStream.of(numbers).skip(3);              // skip first 3
IntStream.of(numbers).filter(n -> n%2==0);  // only even
IntStream.of(numbers).map(n -> n*2);        // double each num
IntStream.of(numbers).boxed();              // convert each num to Integer
Consumir la corriente
IntStream.of(numbers).min();                // min
IntStream.of(numbers).max();                // max
IntStream.of(numbers).sum();                // sum
IntStream.of(numbers).average();            // average
IntStream.of(numbers).count();              // count

IntStream.range(1, 100).forEach(System.out::println);         // print 1 to 99
IntStream.range(1, 100).toArray();                            // collect into array
IntStream.range(1, 100).boxed().collect(Collectors.toList()); // collect into list

IntStream.of(numbers).anyMatch(n -> n%2==1);   // is any num odd
IntStream.of(numbers).allMatch(n -> n%2==1);   // are all num odd

Array.stream()


De manera similar a IntStream, podemos crear una transmisión a partir de una matriz usando Array.stream() y aplicar operaciones similares

int[] intArray = new int[]{1, 3, 5, 7, 9, 3, 5, 99};

int min    = Arrays.stream(nums).min().getAsInt();
int max    = Arrays.stream(nums).max().getAsInt();
double avg = Arrays.stream(nums).average().getAsDouble();
long count = Arrays.stream(nums).count();
long sum   = Arrays.stream(nums).sum();

Arrays.stream(intArray)
        .distinct()
        .forEach(System.out::println);

Si quieres conocer otros artículos parecidos a Flujo en Java 8 - Conceptos de codificación N puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas