Einführung in StreamEx

1. Überblick

Eine der aufregendsten Funktionen von Java 8 ist der Link:/java-8-streams[ Stream API]- ein einfaches Werkzeug zur Verarbeitung von Elementsequenzen.

StreamEx ist eine Bibliothek, die neben den Leistungsverbesserungen zusätzliche Funktionen für die Standard-Stream-API bietet.

Hier sind einige Kernfunktionen:

  • Kürzere und bequemere Wege, um die täglichen Aufgaben zu erledigen

  • 100% ige Kompatibilität mit dem ursprünglichen JDK Streams

  • Freundlichkeit für die parallele Verarbeitung: Jede neue Funktion erfordert

Vorteil bei parallelen Streams so weit wie möglich ** Leistung und minimaler Aufwand. Wenn StreamEx das Lösen der

Task, die im Vergleich zu Standard Stream weniger Code verwendet, sollte nicht wesentlich langsamer sein als üblich (und manchmal sogar noch schneller)

In diesem Lernprogramm werden einige Funktionen der StreamEx -API vorgestellt

** 2. Einrichten des Beispiels

**

Um StreamEx verwenden zu können, müssen wir die folgende Abhängigkeit zu pom.xml hinzufügen:

<dependency>
    <groupId>one.util</groupId>
    <artifactId>streamex</artifactId>
    <version>0.6.5</version>
</dependency>

Die neueste Version der Bibliothek finden Sie unter Maven Zentral .

In diesem Tutorial verwenden wir eine einfache User -Klasse:

public class User {
    int id;
    String name;
    Role role = new Role();

   //standard getters, setters, and constructors
}

Und eine einfache Role -Klasse:

public class Role {
}

** 3. Collectors-Shortcut-Methoden

**

Eine der beliebtesten Terminaloperationen von Streams ist die collect -Operation. Dies ermöglicht das Umpacken von Stream -Elementen in eine Sammlung unserer Wahl.

Das Problem ist, dass Code für einfache Szenarien unnötig ausführlich werden kann:

users.stream()
  .map(User::getName)
  .collect(Collectors.toList());

3.1. Sammeln zu einer Sammlung

Mit StreamEx müssen wir jetzt keinen Collector angeben, um anzugeben, dass wir eine List , Set, Map, InmutableList, usw. benötigen.

List<String> userNames = StreamEx.of(users)
  .map(User::getName)
  .toList();

Die collect -Operation ist immer noch in der API verfügbar, wenn etwas komplizierter ausgeführt werden soll, als Elemente aus einem Stream zu nehmen und in eine Collection zu packen. **

3.2. Fortgeschrittene Sammler

Eine andere Abkürzung ist groupingBy :

Map<Role, List<User>> role2users = StreamEx.of(users)
  .groupingBy(User::getRole);

Dadurch wird ein Map mit dem in der Methodenreferenz angegebenen Schlüsseltyp erzeugt, der durch eine Operation in SQL der Gruppe ähnelt.

Mit der einfachen Stream -API müssen wir schreiben:

Map<Role, List<User>> role2users = users.stream()
  .collect(Collectors.groupingBy(User::getRole));

Eine ähnliche Abkürzungsform kann für Collectors.joining () gefunden werden:

StreamEx.of(1, 2, 3)
  .joining("; ");//"1; 2; 3"

Dadurch werden alle Elemente im Stream a als String zusammengefasst.

4. Elemente hinzufügen, entfernen und auswählen

In einigen Szenarien haben wir eine Liste von Objekten verschiedener Typen, die nach Typ gefiltert werden müssen:

List usersAndRoles = Arrays.asList(new User(), new Role());
List<Role> roles = StreamEx.of(usersAndRoles)
  .select(Role.class)
  .toList();
  • Wir können Elemente mit dem Anfang oder Ende unseres Stream ** , mit diesen praktischen Operationen hinzufügen:

List<String> appendedUsers = StreamEx.of(users)
  .map(User::getName)
  .prepend("(none)")
  .append("LAST")
  .toList();
  • Wir können unerwünschte Nullelemente mit nonNull () ** entfernen und Stream als Iterable verwenden:

for (String line : StreamEx.of(users).map(User::getName).nonNull()) {
    System.out.println(line);
}

5. Unterstützung für mathematische Operationen und primitive Typen

StreamEx fügt Unterstützung für primitive Typen hinzu, wie wir in diesem selbsterklärenden Beispiel sehen können:

short[]src = {1,2,3};
char[]output = IntStreamEx.of(src)
  .map(x -> x **  5)
  .toCharArray();

Lassen Sie uns nun ein Array von double -Elementen ungeordnet aufnehmen. Wir möchten ein Array erstellen, das aus der Differenz zwischen jedem Paar besteht.

Wir können die Methode pairMap verwenden, um diesen Vorgang auszuführen:

public double[]getDiffBetweenPairs(double... numbers) {
    return DoubleStreamEx.of(numbers)
      .pairMap((a, b) -> b - a)
      .toArray();
}

6. Kartenvorgänge

6.1. Filtern nach Schlüsseln

Eine weitere nützliche Funktion ist die Möglichkeit, einen Stream aus einer Map zu erstellen und die Elemente anhand der Werte zu filtern, auf die sie zeigen.

In diesem Fall übernehmen wir alle Nicht-Null-Werte:

Map<String, Role> nameToRole = new HashMap<>();
nameToRole.put("first", new Role());
nameToRole.put("second", null);
Set<String> nonNullRoles = StreamEx.ofKeys(nameToRole, Objects::nonNull)
  .toSet();

6.2. Betrieb auf Schlüsselwertpaaren

Wir können auch Schlüssel-Wert-Paare bearbeiten, indem Sie eine EntryStream -Instanz erstellen:

public Map<User, List<Role>> transformMap(
    Map<Role, List<User>> role2users) {
    Map<User, List<Role>> users2roles = EntryStream.of(role2users)
     .flatMapValues(List::stream)
     .invert()
     .grouping();
    return users2roles;
}

Die spezielle Operation EntryStream.of nimmt eine Map und wandelt sie in einen Stream von Schlüsselwertobjekten um. Dann verwenden wir die flatMapValues -Operation, um unsere Rollenliste in einen Stream von Einzelwerten umzuwandeln.

Als Nächstes können wir das Schlüssel-Wert-Paar invertieren, wobei die User -Klasse der Schlüssel und die Role__-Klasse der Wert ist.

Und schließlich können wir die grouping -Operation verwenden, um unsere Karte mit nur vier Operationen in die Inversion der empfangenen umzuwandeln.

6.3. Schlüsselwertzuordnung

Wir können Schlüssel und Werte auch unabhängig voneinander zuordnen:

Map<String, String> mapToString = EntryStream.of(users2roles)
  .mapKeys(String::valueOf)
  .mapValues(String::valueOf)
  .toMap();

Damit können wir unsere Schlüssel oder Werte schnell in einen anderen erforderlichen Typ umwandeln.

7. Dateivorgänge

Mit StreamEx können wir Dateien effizient lesen, d. H. Ohne vollständige Dateien auf einmal zu laden. Es ist praktisch, wenn Sie große Dateien bearbeiten:

StreamEx.ofLines(reader)
  .remove(String::isEmpty)
  .forEach(System.out::println);

Beachten Sie, dass wir die Methode remove () verwendet haben, um leere Zeilen herauszufiltern.

Hierbei ist zu beachten, dass StreamEx die Datei nicht automatisch schließt. Daher müssen wir daran denken, die Schließoperation sowohl beim Lesen als auch beim Schreiben von Dateien manuell auszuführen, um unnötigen Speicheraufwand zu vermeiden.

8. Fazit

In diesem Lernprogramm haben wir etwas über StreamEx und die verschiedenen Dienstprogramme erfahren. Es gibt noch viel mehr zu erledigen - und sie haben einen praktischen Spickzettel https://github.com/amaembo/streamex/blob/master/CHEATSHEET.md [hier