JavaRush /Blog Java /Random-ES /Pausa para el café #108. 12 usos comunes de Java Streams,...

Pausa para el café #108. 12 usos comunes de Java Streams, cómo evaluar la asignación de memoria de un objeto en Java

Publicado en el grupo Random-ES

12 formas comunes de utilizar Java Streams

Fuente: Dev.to La API Java Streams apareció por primera vez en Java 8. Su propósito es proporcionar una forma más compacta de realizar operaciones comunes en colecciones de objetos. Además, la API Java Streams se puede utilizar para implementar algoritmos complejos. En este artículo, hablaremos sobre casos de uso comunes de Java Streams. Pausa para el café #108.  12 usos comunes de Java Streams, cómo evaluar la asignación de memoria de un objeto en Java - 1Primero, aclaremos algunos conceptos básicos:
  • stream() : crea una secuencia a partir de la colección.

  • Collect() : recopila una secuencia en un objeto. Un objeto puede ser una colección, una primitiva o una clase personalizada.

  • Collectors es una clase que proporciona (muchos) métodos estáticos para recopilar transmisiones.

Ahora veamos algunos casos de uso de Streams:

1. Filtrado

  • Se utiliza para eliminar valores de una Colección según una condición.

  • Para filtrar elementos de la colección según una condición, utilice el método filter() . Sólo se guardan los elementos coincidentes.

Ejemplo: eliminar todos los números impares de la lista.
List<Integer> evenNumbers = originalList.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());

2. Preprocesamiento

  • Útil cuando es necesario cambiar todos los valores de una colección.

  • El método map() se utiliza para aplicar una función a cada elemento de la colección y devolver una nueva colección de valores calculados.

Por ejemplo, convierta cada valor a su cuadrado.
List<Integer> squares = originalList.stream()
        .map(n -> n * n)
        .collect(Collectors.toList());

3. Conversión

  • Útil cuando queremos transformar una colección en otra colección.

  • Hay varias formas de lograrlo.

Como se mencionó anteriormente, podemos usar los métodos map() y Collect() para transformar una colección en otra colección.

Ejemplo 1: crear un mapa a partir de listas.

Convierta una lista de cadenas en un mapa de cadenas y longitudes.
Map<String, Integer> wordLengths = words.stream()
        .collect(Collectors.toMap(
                word -> word,
                word -> word.length()));

Ejemplo 2. Convertir una lista en conjuntos.

Este es un caso de uso común para eliminar duplicados. Además, si queremos volver a colocar elementos en la lista, podemos usar los métodos stream() y Collect() dos veces . Por ejemplo, conviertamos una lista de cadenas en una lista de cadenas únicas:
// if we want to collect to a set
Set<String> uniqueWords = words.stream()
        .collect(Collectors.toSet());

// OR

// if we want to start and end as a list
List<String> uniqueWords = words.stream()
        .collect(Collectors.toSet()).stream().collect(Collectors.toList());

Ejemplo 3. Convertir una lista de productos en una lista de sus nombres. (Aplanamiento - Alineación)

List<String> productNames = products.stream()
        .map(product -> product.getName())
        .collect(Collectors.toList());

4. Reducción

  • Reduce la colección a un solo valor.

  • El método reduce() se utiliza para aplicar una función a cada elemento de la colección y devolver un valor único.

Tenga en cuenta que dado que el método reduce() devuelve un valor único, no se puede utilizar para devolver una Colección. Ejemplo, sumamos todos los valores de la lista:
int sum = numbers.stream()
        .reduce(0, (a, b) -> a + b);

5. Agrupación

  • Agrupa los elementos de una Colección según una condición determinada.

  • Para agrupar elementos de la Colección por condición, utilice el método Collectors.groupingBy() .

Por ejemplo, agrupemos todos los productos en listas de productos por categorías.
Map<String, List<Product>> productsByCategory = products.stream()
        .collect(Collectors.groupingBy(product -> product.getCategory()));

6. Encontrar

  • Busca el primer elemento de la Colección o cualquier elemento que coincida con una condición.

  • Los métodos findFirst() y findAny() se utilizan para realizar búsquedas .

Esto suele ser similar a una búsqueda lineal. Por ejemplo, buscamos la primera palabra de la lista cuya longitud supere los 5 caracteres.
Optional<String> firstLongWord = words.stream()
        .filter(word -> word.length() > 5)
        .findFirst();
// Note that findFirst() and findAny() methods return Optional<T> objects.

7. Clasificación

  • Ordena los elementos de Colecciones.

  • El método sorted() se utiliza para ordenar .

Generalmente, Collections.sort() es suficiente para ordenar una colección. Podemos usar sorted() específicamente si queremos ejecutar otra operación. Por ejemplo, ordenemos una lista de números en orden ascendente y luego devolvamos los primeros k elementos.
List<Integer> topK = numbers.stream()
        .sorted()
        .limit(k)
        .collect(Collectors.toList());

8. Partición

  • Separa los elementos de una Colección en función de una condición determinada.

  • El método Collectors.partitioningBy() se utiliza para separar elementos .

Una división es similar a un grupo, excepto que devuelve dos colecciones: una para los elementos que coinciden con la condición y otra para los elementos que no coinciden con la condición. Por ejemplo, dividamos a los estudiantes entre los que aprobaron el examen y los que no lo reprobaron.
Map<Boolean, List<Student>> passingFailing = students
        .stream()
        .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));

9. Contando

  • Cuenta el número de elementos que coinciden con una condición.

  • El método count() se utiliza para contar el número de elementos que coinciden con una condición .

Por ejemplo, contamos la cantidad de palabras en la lista cuya longitud excede los 5 caracteres.
long count = words.stream()
        .filter(word -> word.length() > 5)
        .count();

10. rango

  • Crea un rango de valores.

  • Para crear un rango de valores, utilice el método range() .

Existen clases especiales para crear transmisiones de ciertos tipos: IntStream , LongStream , DoubleStream y Stream . Estas clases son útiles cuando se trabaja con tipos numéricos primitivos. Para convertir una matriz en una secuencia, use Arrays.stream() . Por ejemplo, creemos una matriz de números del 0 al 10.
int[] numbers = IntStream.range(0, 10).toArray();

11. Coincidencia

  • Relaciona los elementos de una colección con un predicado (condición).

  • Métodos como anyMatch() , allMatch() y noneMatch() se utilizan para hacer coincidir elementos de la colección con un predicado y devolver un valor booleano .

Por ejemplo, revisemos productos con un precio superior a 10.
// true when all elements match the predicate
boolean allMatch = products.stream()
        .allMatch(product -> product.getPrice() > 10);

// true when any element matches the predicate
boolean anyMatch = products.stream()
        .anyMatch(product -> product.getPrice() > 10);

// true when no elements match the predicate
boolean noneMatch = products.stream()
        .noneMatch(product -> product.getPrice() > 10);

12. Unirse

  • Concatena los elementos de una colección en una cadena.

  • Para unir elementos de la colección en una cadena, utilice el método Collectors.joining() .

Por ejemplo, concatenemos todas las palabras de una lista en una sola cadena.
String joinedWords = words.stream()
        .collect(Collectors.joining(" "));
Eso es todo para escenarios generales. Hay otros escenarios menos comunes que puedes explorar por tu cuenta:
  • Corrientes paralelas;
  • Estadísticas;
  • Coleccionistas personalizados.

Beneficios de los hilos

  • Código más compacto: reduce la cantidad de código necesario para procesar la colección.

  • Menos variables intermedias. Las variables que intervienen pueden provocar que se produzcan errores. Cuantos menos sean, más fácil será evitar errores inesperados.

  • Código intuitivo. Algunos desarrolladores no estarán de acuerdo con que los subprocesos sean más intuitivos que otros métodos. Sin embargo, una vez que nos acostumbramos a ellos, se vuelven mucho más intuitivos que otros métodos.

Gracias por leer. Espero que hayas disfrutado de este artículo. Hay muchos más casos en los que se pueden utilizar subprocesos que no se tratan en este tema. Siéntase libre de agregar cualquier escenario común que me haya perdido.

Cómo evaluar la asignación de memoria de un objeto en Java

Fuente: DZone Este artículo muestra las tres formas más conocidas de evaluar la asignación de memoria de un objeto en Java.

Evaluación de la memoria usando Profiler

La forma más sencilla de estimar la memoria de algunos objetos es buscar directamente en la memoria JVM utilizando un generador de perfiles como Visual VM . Pausa para el café #108.  12 usos comunes de Java Streams, cómo evaluar la asignación de memoria de un objeto en Java - 2El problema con este enfoque es que necesita conectarse a una JVM en ejecución, lo que puede no ser posible en entornos de producción por razones de seguridad.

Evaluación de la memoria mediante instrumentos.

Otra forma de estimar la memoria asignada para un objeto determinado es utilizar Instrumentos. En términos simples, necesitamos crear una clase y compilarla en un JAR. Después de crear el JAR, debemos ejecutar nuestra JVM junto con ese JAR. Puedes encontrar más información sobre este método aquí . La desventaja aquí es la necesidad de agregar un archivo jar específico a la JVM, que puede no ser aceptable para producción debido a problemas de seguridad o relacionados.

Evaluación de la memoria utilizando la biblioteca JOL

Como otra opción, podemos utilizar JOL Library . Esta es una biblioteca muy poderosa que puede proporcionar una estimación detallada del peso de un objeto y la memoria asignada por una instancia de objeto. Para usar la biblioteca, necesitamos agregar una dependencia:
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>
Después de eso podemos usarlo así:
out.println(GraphLayout.parseInstance(myObject).totalSize() / 1024000d + " MB")

ObjectSizeCalculator del archivo de Twitter

El repositorio público de GitHub de Twitter tiene una clase de herramienta llamada ObjectSizeCalculator que puede estimar la memoria asignada para una instancia de objeto determinada. No requiere mucha memoria ni tiempo para su uso. El proceso de evaluación dura unos segundos, incluso para objetos grandes. Usar esta clase es bastante simple:
ObjectSizeCalculator.getObjectSize(address)
Recomiendo este método, pero tenga en cuenta que sólo es compatible con Java Hotspot, OpenJDK y TwitterJDK.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION