JavaRush /Java-Blog /Random-DE /Kaffeepause Nr. 108. 12 häufige Verwendungen von Java-Str...

Kaffeepause Nr. 108. 12 häufige Verwendungen von Java-Streams, Bewerten der Speicherzuweisung eines Objekts in Java

Veröffentlicht in der Gruppe Random-DE

12 gängige Möglichkeiten zur Verwendung von Java Streams

Quelle: Dev.to Die Java Streams API erschien erstmals in Java 8. Ihr Zweck besteht darin, eine kompaktere Möglichkeit zur Durchführung allgemeiner Operationen an Objektsammlungen bereitzustellen. Außerdem kann die Java Streams API zur Implementierung komplexer Algorithmen verwendet werden. In diesem Artikel werden wir über häufige Anwendungsfälle von Java Streams sprechen. Kaffeepause Nr. 108.  12 häufige Verwendungen von Java-Streams, So bewerten Sie die Speicherzuweisung eines Objekts in Java – 1Lassen Sie uns zunächst einige Grundlagen klären:
  • stream() – erstellt einen Stream aus der Sammlung.

  • Collect() – sammelt einen Stream in einem Objekt. Ein Objekt kann eine Sammlung, ein Grundelement oder eine benutzerdefinierte Klasse sein.

  • Collectors ist eine Klasse, die (viele) statische Methoden zum Sammeln von Streams bereitstellt.

Schauen wir uns nun einige Anwendungsfälle für Streams an:

1. Filtern

  • Wird verwendet, um Werte basierend auf einer Bedingung aus einer Sammlung zu entfernen.

  • Um Sammlungselemente basierend auf einer Bedingung zu filtern, verwenden Sie die Methode filter() . Es werden nur passende Elemente gespeichert.

Beispiel: Alle ungeraden Zahlen aus der Liste entfernen.
List<Integer> evenNumbers = originalList.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());

2. Vorverarbeitung

  • Nützlich, wenn jeder Wert in einer Sammlung direkt geändert werden muss.

  • Die Methode „map()“ wird verwendet, um eine Funktion auf jedes Element der Sammlung anzuwenden und eine neue Sammlung berechneter Werte zurückzugeben.

Lassen Sie uns zum Beispiel jeden Wert in sein Quadrat umwandeln.
List<Integer> squares = originalList.stream()
        .map(n -> n * n)
        .collect(Collectors.toList());

3. Konvertierung

  • Nützlich, wenn wir eine Sammlung in eine andere Sammlung umwandeln möchten.

  • Es gibt mehrere Möglichkeiten, dies zu erreichen.

Wie oben erwähnt, können wir die Methoden „map()“ und „collect()“ verwenden , um eine Sammlung in eine andere Sammlung umzuwandeln.

Beispiel 1: Erstellen Sie eine Karte aus Listen.

Konvertieren Sie eine Liste von Zeichenfolgen in eine Zuordnung von Zeichenfolgen und Längen.
Map<String, Integer> wordLengths = words.stream()
        .collect(Collectors.toMap(
                word -> word,
                word -> word.length()));

Beispiel 2. Konvertieren einer Liste in Mengen.

Dies ist ein häufiger Anwendungsfall zum Entfernen von Duplikaten. Wenn wir Elemente wieder in die Liste einfügen möchten, können wir außerdem die Methoden stream() und Collect() zweimal verwenden . Lassen Sie uns beispielsweise eine Liste von Zeichenfolgen in eine Liste eindeutiger Zeichenfolgen konvertieren:
// 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());

Beispiel 3. Konvertieren einer Produktliste in eine Liste ihrer Namen. (Abflachung – Ausrichtung)

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

4. Reduzierung

  • Reduziert die Sammlung auf einen einzelnen Wert.

  • Die Methode „reduce()“ wird verwendet, um eine Funktion auf jedes Element der Sammlung anzuwenden und einen einzelnen Wert zurückzugeben.

Beachten Sie, dass die Methode „reduce()“ einen einzelnen Wert zurückgibt und daher nicht zur Rückgabe einer Sammlung verwendet werden kann. Beispiel: Wir fassen alle Werte in der Liste zusammen:
int sum = numbers.stream()
        .reduce(0, (a, b) -> a + b);

5. Gruppierung

  • Gruppiert die Elemente einer Sammlung basierend auf einer bestimmten Bedingung.

  • Um Sammlungselemente nach Bedingung zu gruppieren, verwenden Sie die Methode Collectors.groupingBy() .

Lassen Sie uns beispielsweise alle Produkte nach ihren Kategorien in Produktlisten gruppieren.
Map<String, List<Product>> productsByCategory = products.stream()
        .collect(Collectors.groupingBy(product -> product.getCategory()));

6. Finden

  • Sucht nach dem ersten oder einem beliebigen Collection-Element, das einer Bedingung entspricht.

  • Für die Suche werden die Methoden findFirst() und findAny() verwendet .

Dies ähnelt normalerweise einer linearen Suche. Wir suchen beispielsweise nach dem ersten Wort in der Liste, dessen Länge mehr als 5 Zeichen beträgt.
Optional<String> firstLongWord = words.stream()
        .filter(word -> word.length() > 5)
        .findFirst();
// Note that findFirst() and findAny() methods return Optional<T> objects.

7. Sortieren

  • Sortiert die Elemente von Sammlungen.

  • Zum Sortieren wird die Methode sorted() verwendet .

Im Allgemeinen reicht Collections.sort() aus, um eine Sammlung zu sortieren. Wir können sorted() speziell verwenden, wenn wir eine andere Operation ausführen möchten. Sortieren wir beispielsweise eine Liste mit Zahlen in aufsteigender Reihenfolge und geben dann die ersten k Elemente zurück.
List<Integer> topK = numbers.stream()
        .sorted()
        .limit(k)
        .collect(Collectors.toList());

8. Partitionierung

  • Trennt die Elemente einer Sammlung basierend auf einer bestimmten Bedingung.

  • Die Methode Collectors.partitioningBy() wird zum Trennen von Elementen verwendet .

Eine Aufteilung ähnelt einer Gruppe, außer dass sie zwei Sammlungen zurückgibt – eine für die Elemente, die der Bedingung entsprechen, und eine für die Elemente, die der Bedingung nicht entsprechen. Teilen wir die Schüler zum Beispiel in diejenigen ein, die die Prüfung bestanden haben, und diejenigen, die sie nicht bestanden haben.
Map<Boolean, List<Student>> passingFailing = students
        .stream()
        .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));

9. Zählen

  • Zählt die Anzahl der Elemente, die einer Bedingung entsprechen.

  • Mit der Methode count() wird die Anzahl der Elemente gezählt, die einer Bedingung entsprechen .

Zählen wir beispielsweise die Anzahl der Wörter in der Liste, deren Länge 5 Zeichen überschreitet.
long count = words.stream()
        .filter(word -> word.length() > 5)
        .count();

10. Reichweite

  • Erstellt einen Wertebereich.

  • Um einen Wertebereich zu erstellen, verwenden Sie die Methode range() .

Es gibt spezielle Klassen zum Erstellen von Streams bestimmter Typen – IntStream , LongStream , DoubleStream und Stream . Diese Klassen sind nützlich, wenn Sie mit primitiven numerischen Typen arbeiten. Um ein Array in einen Stream umzuwandeln, verwenden Sie Arrays.stream() . Lassen Sie uns zum Beispiel ein Array mit Zahlen von 0 bis 10 erstellen.
int[] numbers = IntStream.range(0, 10).toArray();

11. Passend

  • Ordnet die Elemente einer Sammlung einem Prädikat (Bedingung) zu.

  • Methoden wie anyMatch() , allMatch() und noneMatch() werden verwendet, um Sammlungselemente mit einem Prädikat abzugleichen und einen booleschen Wert zurückzugeben .

Schauen wir uns zum Beispiel Produkte an, deren Preis über 10 liegt.
// 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. Beitritt

  • Verkettet die Elemente einer Sammlung zu einer Zeichenfolge.

  • Um Sammlungselemente zu einer Zeichenfolge zusammenzufügen, verwenden Sie die Methode Collectors.joining() .

Lassen Sie uns beispielsweise alle Wörter in einer Liste zu einer Zeichenfolge verketten.
String joinedWords = words.stream()
        .collect(Collectors.joining(" "));
Das war's für allgemeine Szenarien. Es gibt andere, weniger häufige Szenarien, die Sie selbst erkunden können:
  • Parallele Streams;
  • Statistiken;
  • Benutzerdefinierte Sammler.

Vorteile von Threads

  • Kompakterer Code – reduziert die Menge an Code, die zum Verarbeiten der Sammlung erforderlich ist.

  • Weniger Zwischenvariablen. Durch eingreifende Variablen kann es zu Fehlern kommen. Je weniger es sind, desto einfacher lassen sich unerwartete Fehler vermeiden.

  • Intuitiver Code. Einige Entwickler sind anderer Meinung, dass Threads intuitiver sind als andere Methoden. Sobald wir uns jedoch daran gewöhnt haben, werden sie viel intuitiver als andere Methoden.

Vielen Dank fürs Lesen. Ich hoffe, Ihnen hat dieser Artikel gefallen. Es gibt viele weitere Fälle, in denen Threads verwendet werden können, die in diesem Thema nicht behandelt werden. Fühlen Sie sich frei, ein häufiges Szenario hinzuzufügen, das ich verpasst habe.

So bewerten Sie die Speicherzuordnung eines Objekts in Java

Quelle: DZone Dieser Artikel zeigt die drei bekanntesten Methoden zur Bewertung der Speicherzuordnung eines Objekts in Java.

Gedächtnisbewertung mit Profiler

Der einfachste Weg, den Speicher einiger Objekte abzuschätzen, besteht darin, mit einem Profiler wie Visual VM direkt in den JVM-Speicher zu schauen . Kaffeepause Nr. 108.  12 häufige Verwendungen von Java-Streams, So bewerten Sie die Speicherzuweisung eines Objekts in Java - 2Das Problem bei diesem Ansatz besteht darin, dass Sie eine Verbindung zu einer laufenden JVM herstellen müssen, was aus Sicherheitsgründen in Produktionsumgebungen möglicherweise nicht möglich ist.

Gedächtnisbewertung mit Instrumenten

Eine andere Möglichkeit, den zugewiesenen Speicher für ein bestimmtes Objekt abzuschätzen, ist die Verwendung von Instrumenten. Vereinfacht ausgedrückt müssen wir eine Klasse erstellen und diese in ein JAR kompilieren. Nachdem wir die JAR erstellt haben, müssen wir unsere JVM zusammen mit dieser JAR ausführen. Mehr über diese Methode erfahren Sie hier . Der Nachteil besteht darin, dass der JVM eine bestimmte JAR-Datei hinzugefügt werden muss, die aus Sicherheits- oder ähnlichen Gründen möglicherweise nicht für die Produktion geeignet ist.

Gedächtnisbewertung mit der JOL-Bibliothek

Als weitere Option können wir die JOL-Bibliothek verwenden . Dies ist eine sehr leistungsstarke Bibliothek, die eine detaillierte Schätzung des Gewichts eines Objekts und des von einer Objektinstanz zugewiesenen Speichers liefern kann. Um die Bibliothek nutzen zu können, müssen wir eine Abhängigkeit hinzufügen:
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>
Danach können wir es wie folgt verwenden:
out.println(GraphLayout.parseInstance(myObject).totalSize() / 1024000d + " MB")

ObjectSizeCalculator aus dem Twitter-Archiv

Das öffentliche GitHub- Repository von Twitter verfügt über eine Toolklasse namens ObjectSizeCalculator , die den zugewiesenen Speicher für eine bestimmte Objektinstanz schätzen kann. Die Verwendung erfordert nicht viel Speicher oder Zeit. Der Auswertungsprozess dauert selbst bei großen Objekten Sekunden. Die Verwendung dieser Klasse ist ganz einfach:
ObjectSizeCalculator.getObjectSize(address)
Ich empfehle diese Methode, bedenken Sie jedoch, dass sie nur von Java Hotspot, OpenJDK und TwitterJDK unterstützt wird.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION