Probieren Sie verschiedene Java Stream API-Methoden aus (jetzt)

Stream-API in Java 8 hinzugefügt. Ich habe nach Bedarf recherchiert und das Minimum verwendet, aber ich habe es nicht gut verstanden, also habe ich es erneut untersucht und ausprobiert.

Was ist die Stream-API überhaupt?

"Eine Klasse, die funktionale Operationen für einen Strom von Elementen unterstützt". https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/package-summary.html … Das offizielle Dokument ist schwer zu lesen, wahrscheinlich weil es eine automatische Übersetzung ist. Sie können verstehen, wer Englisch liest ...

Das "Element" hier scheint sich hauptsächlich auf Sammlungselemente wie List zu beziehen. Stream ist genau so, wie es in diesem Artikel geschrieben steht. https://qiita.com/castaneai/items/3dbdd8543b020aa903cb

Wofür ist StreamAPI nützlich?

Meine Interpretation ist

Stream API Übersicht

Ich hatte das Gefühl, dass JavaDoc für die Stream-Oberfläche die Basis für alles sein würde, deshalb werde ich mich hier darauf konzentrieren. https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html

Prozessablauf

  1. Erstellen Sie einen Stream aus einer Quelle (z. B. Liste).
  2. 0 bis n Zwischenoperationen
  3. Eine Beendigungsoperation

スクリーンショット 2018-12-05 6.06.52.png

Punkt (Auszug aus JavaDoc)

Es ist vorerst ein Experiment!

Abgeleitete Dinge wie Methoden, die IntStream zurückgeben, werden ausgeschlossen.

Davor

Ich habe eine Bean und eine Methode zum Erstellen von Testdaten erstellt. Ich rufe es von der Hauptmethode aus auf, erstelle eine Variable namens list und experimentiere dann.

Bean

Bean


public class TestBean {
	String key;
	String value;
	String description;
	public TestBean(String key, String value, String description) {
		this.setKey(key);
		this.setValue(value);
		this.setDescription(description);
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	@Override
	public String toString() {
		return "key:" + this.key + " value:" + this.value + " description:" + this.description;
	}
}
Methode

Testdatenerstellungsmethode


	private static List<TestBean> editTestData() {
		List<TestBean> list = new ArrayList<>();
		list.add(new TestBean("B", "Butaman", "Enthält Schweinefleisch"));
		list.add(new TestBean("A", "Anman", "Enthält Anko"));
		list.add(new TestBean("C", "Chukaman", "Es ist ein allgemeiner Begriff für Anmanbutaman usw."));
		return list;
	}

Zwischenbetrieb

filter Wie der Name schon sagt, hat es gefiltert!

filter


list.stream()
.filter(x -> x.getValue().equals("Anman"))
.forEach(x -> System.out.println(x.getDescription()));

Ausführungsergebnis


Enthält Anko

map Ich habe es so interpretiert, dass es einen anderen Stream basierend auf dem Stream erstellt. In diesem Beispiel wird ein Stream vom Typ TestBean durch einen Stream aus String ersetzt.

map


list.stream()
.map(x -> x.getKey() + x.getValue() + x.getDescription())
.forEach(x -> System.out.println(x));

Ausführungsergebnis


B Butaman enthält Schweinefleisch
Ein Anman Anko ist enthalten
C Chukaman Anmanbutaman usw.

flatMap Es scheint, dass Sie einen Stream innerhalb eines Streams erstellen können. Ein Bild wie eine Tabelle mit Stream erstellen? Hier wird jedes Element der Bean, aus dem eine Zeile besteht, getrennt, um einen weiteren Stream zu erstellen.

flatMap


list.stream()
.flatMap(x -> Stream.of(Arrays.asList(x.getKey(),x.getValue(),x.getDescription())))
.forEach(x -> x.forEach(y -> System.out.println(y)));

Ausführungsergebnis


B
Butaman
Enthält Schweinefleisch
A
Anman
Enthält Anko
C
Chukaman
Es ist ein allgemeiner Begriff für Anmanbutaman usw.

distinct Beseitigen Sie doppelte Elemente. Bei der Durchführung dieses Tests haben wir die obigen Testdaten aufgeblasen.

Testdaten

Testdaten (Duplikat a)


	private static List<TestBean> editTestData() {
		List<TestBean> list = new ArrayList<>();
		TestBean a = new TestBean("A", "Anman", "Enthält Anko");
		TestBean b = new TestBean("B", "Butaman", "Enthält Schweinefleisch");
		TestBean c = new TestBean("C", "Chukaman", "Es ist ein allgemeiner Begriff für Anmanbutaman usw.");
		list.add(b);
		list.add(a);
		list.add(a);
		list.add(a);
		list.add(c);
		return list;
	}
Keine eindeutige

Quelle


list.stream()
.forEach(x -> System.out.println(x.getDescription()));

Ausführungsergebnis


Enthält Schweinefleisch
Enthält Anko
Enthält Anko
Enthält Anko
Es ist ein allgemeiner Begriff für Anmanbutaman usw.
mit eindeutiger

Quelle


list.stream()
.distinct()
.forEach(x -> System.out.println(x.getDescription()));

Ausführungsergebnis


Enthält Schweinefleisch
Enthält Anko
Es ist ein allgemeiner Begriff für Anmanbutaman usw.

sorted Sortieren wie der Name schon sagt. In diesem Beispiel werden die Elemente mit dem Namen key (ABC) der Reihe nach sortiert.

sorted


list.stream()
.sorted((o1, o2) -> o1.getKey().compareTo(o2.getKey()))
.forEach(x -> System.out.println(x.getKey() + x.getValue() + x.getDescription()));

Ausführungsergebnis


Ein Anman Anko ist enthalten
B Butaman enthält Schweinefleisch
C Chukaman Anmanbutaman usw.

peek Dies manipuliert den Inhalt des Streams nicht speziell. Es sieht aus wie eine Methode zum Debuggen. peek = Ein Blick (wörtlich übersetzt)

peek


list.stream()
.peek(x -> System.out.println(x))
.forEach(x -> System.out.println("Ausgabe mit forEach"));

Ausführungsergebnis


key:B value:Butaman Beschreibung:Enthält Schweinefleisch
Ausgabe mit forEach
key:A value:Anman Beschreibung:Enthält Anko
Ausgabe mit forEach
key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.
Ausgabe mit forEach

Ich habe mich gefragt, ob forEach durchgeführt werden würde, nachdem alle Peeks zuerst durchgeführt wurden, aber es scheint, dass für jedes Element eine Zwischenverarbeitung → Terminierungsverarbeitung durchgeführt wird.

limit Schneiden Sie die Anzahl der Streams auf die angegebene Anzahl ab.

limit


list.stream()
.limit(2)
.forEach(x -> System.out.println(x));

Ausführungsergebnis


key:B value:Butaman Beschreibung:Enthält Schweinefleisch
key:A value:Anman Beschreibung:Enthält Anko

skip Im Gegensatz zum Limit wird der Beginn des Streams übersprungen.

skip


list.stream()
.skip(1)
.forEach(x -> System.out.println(x));

Ausführungsergebnis


key:A value:Anman Beschreibung:Enthält Anko
key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.

Kündigungsoperation

forEach Ich habe es bisher jedes Mal beiläufig benutzt. Verarbeitet alle Elemente von Stream. … Aber es scheint, dass die Bestellung nicht garantiert ist. Nur für parallele Streams?

forEachOrdered Es ist dasselbe wie für jedes, aber es scheint, dass die Bestellung dadurch garantiert wird.

toArray Machen Sie den Stream einfach zu einem Array.

toArray


Object[] testBeans = list.stream().toArray();
System.out.println(testBeans[0].toString());
System.out.println(testBeans[1].toString());

Ausführungsergebnis


key:B value:Butaman Beschreibung:Enthält Schweinefleisch
key:A value:Anman Beschreibung:Enthält Anko

reduce reduzieren = reduzieren, reduzieren (wörtlich) Dies scheint nützlich zu sein, wenn Sie den Inhalt von Stream zusammenfassen. In diesem Beispiel wird das Element mit dem Namen value angehängt. Von Stream wird nur eine Option zurückgegeben. Zusätzlich gibt es eine Reduzierung, die den Anfangswert einstellen kann. Signaturunterschied.

reduce


Optional<TestBean> opt = list.stream()
.reduce((t, u) -> {
  t.setValue(t.getValue() + u.getValue());
  return t;
});
System.out.println(opt.orElse(new TestBean("x", "x", "x")));

Ausführungsergebnis


key:B value:Butaman Anman Chukaman Beschreibung:Enthält Schweinefleisch

collect Es scheint verwendet zu werden, wenn Sie es als Sammlung anstelle eines einzelnen Elements wie Optional zurückgeben möchten. Sammlung → Als Stream bearbeiten → Als Sammlung ausgeben Ich denke, ich benutze es ziemlich oft.

Wenn Sie die verschiedenen Schnittstellen, die die Argumente für das Sammeln sind, ernsthaft selbst implementieren möchten, müssen Sie ungefähr 5 abstrakte Methoden schreiben, damit die in der Collectors-Klasse bereitgestellte statische Methode einfach verwendet werden kann.

collect


List<TestBean> newlist = list.stream()
  .filter(x -> x.getKey().equals("C"))
  .collect(Collectors.toList());
System.out.println(newlist.get(0).toString());

Ausführungsergebnis


key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.

min Wie der Name schon sagt, wird der kleinste als optional zurückgegeben. Das Minimum ist dasselbe wie für das Sortieren, und der Komparator wird implementiert und definiert. Geben Sie in diesem Beispiel das Element mit dem Namen key an.

min


Optional<TestBean> op = list.stream()
  .min((x, y) -> x.getKey().compareTo(y.getKey()));
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());

Ausführungsergebnis


key:A value:Anman Beschreibung:Enthält Anko

max Das Gegenteil von min!

max


Optional<TestBean> op = list.stream()
  .max((x, y) -> x.getKey().compareTo(y.getKey()));
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());

Ausführungsergebnis


key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.

count Wie der Name schon sagt, wird die Anzahl der Stream-Elemente zurückgegeben.

count


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

Ausführungsergebnis


3

anyMatch Während ich lese, gibt es true zurück, wenn eine der Bedingungen in Stream erfüllt ist. In diesem Beispiel suchen wir einen Artikel mit dem Schlüssel "A".

anyMatch


boolean matched = list.stream().anyMatch(x -> x.getKey().equals("A"));
if (matched) {
  System.out.println("Da war ein Mann!");
}

Ausführungsergebnis


Da war ein Mann!

allMatch Bis ich dies gelesen habe, wird true zurückgegeben, wenn alle Elemente in Stream die angegebenen Bedingungen erfüllen.

allMatch


boolean matched = list.stream().allMatch(x -> !x.getKey().equals("Z"));
if (matched) {
  System.out.println("Nicht jeder ist Z!");
}

Ausführungsergebnis


Nicht jeder ist Z!

noneMatch Gibt true zurück, wenn der Stream nicht vorhanden ist.

noneMatch


boolean noMatched = list.stream().noneMatch(x -> x.getKey().equals("Z"));
if (noMatched) {
  System.out.println("Es gab keinen Z-Krieger");
}

Ausführungsergebnis


Es gab keinen Z-Krieger

findFirst Wie der Name schon sagt, wird der erste zurückgegeben!

findFirst


Optional<TestBean> op = list.stream().findFirst();
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());

Ausführungsergebnis


key:B value:Butaman Beschreibung:Enthält Schweinefleisch

findAny Es geht seinen Namen durch und gibt etwas zurück. Ich spreche über etwas ... Ich weiß nicht wirklich, was zurückkommen wird. Sie können kein Argument angeben. Als ich es mit einem sequentiellen Stream versuchte, wurde das erste Element zurückgegeben, aber es scheint, dass es keine Garantie gibt. (08.12.2018 Ich habe einen Kommentar erhalten und korrigiert)

findAny


Optional<TestBean> op = list.stream().findAny();
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());

Ausführungsergebnis


key:B value:Butaman Beschreibung:Enthält Schweinefleisch

Andere Experimente als das Ausprobieren der Methode

Stellen Sie sicher, dass sich die ursprüngliche Quelle nicht geändert hat, auch wenn Sie Stream betreiben

Ich habe das Bean-Wertelement im Stream mit einer festen Zeichenfolge überschrieben. Sicherlich hat sich die Quelle (Liste) nicht geändert.

source

python


System.out.println("【Vor】 ändern");
for (TestBean bean : list) {
  System.out.println(bean);
}

list.stream().map(x -> {
  x.setValue("Ich habe es geändert!");
  return x;
});

System.out.println("[Nach der veränderung]");
for (TestBean bean : list) {
  System.out.println(bean);
}
Ausführungsergebnis

Ausführungsergebnis


【Vor】 ändern
key:B value:Butaman Beschreibung:Enthält Schweinefleisch
key:A value:Anman Beschreibung:Enthält Anko
key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.
[Nach der veränderung]
key:B value:Butaman Beschreibung:Enthält Schweinefleisch
key:A value:Anman Beschreibung:Enthält Anko
key:C value:Chukaman Beschreibung:Es ist ein allgemeiner Begriff für Anmanbutaman usw.

Geschwindigkeitsdifferenz messen

Erstellen Sie eine Liste von 150 Millionen Speichern Sie darin Zufallszahlen von 0 bis 99 Erstellen Sie eine weitere Liste, indem Sie nur die Elemente extrahieren, in denen 99 gespeichert ist Ich habe einen verschwenderischen Prozess gemacht und ihn gemessen.

Infolgedessen gibt es keinen großen Unterschied zwischen Liste und Stream. paralellStream war offensichtlich schnell.

source

python


    final int loopsize = 150000000;
    final int randomrange = 100;
    final int findnum = 99;

    // create many data
    System.out.println("Während der Testdatengenerierung...");
    List<Integer> list = IntStream.range(0, loopsize)
        .mapToObj(x -> new Random().nextInt(randomrange))
        .collect(Collectors.toList());

    // byList
    LocalDateTime starttime = start("--- byList ---");
    List<Integer> newlist = new ArrayList<>();
    for (Integer i : list) {
      if (i.intValue() == findnum) {
        newlist.add(i);
      }
    }
    end(starttime, findnum, newlist);

    // byStream
    starttime = start("--- byStream ---");
    List<Integer> streamlist = list.stream()
        .filter(x -> x.intValue() == findnum).collect(Collectors.toList());
    end(starttime, findnum, streamlist);

    // byParalellStream
    starttime = start("--- byParalellStream ---");
    List<Integer> paralellStreamlist = list.parallelStream()
        .filter(x -> x.intValue() == findnum).collect(Collectors.toList());
    end(starttime, findnum, paralellStreamlist);
  }

  private static LocalDateTime start(String msg) {
    System.out.println("");
    System.out.println(msg);
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println("start: " + ldt);
    return ldt;
  }

  private static void end(LocalDateTime starttime, int findnum,
      List<Integer> newlist) {
    LocalDateTime elapsed = LocalDateTime.now();
    System.out.println("end  : " + elapsed);
    elapsed = elapsed.minusHours(starttime.getHour());
    elapsed = elapsed.minusMinutes(starttime.getMinute());
    elapsed = elapsed.minusSeconds(starttime.getSecond());
    elapsed = elapsed.minusNanos(starttime.getNano());
    System.out
        .println("elapsed: " + elapsed.format(DateTimeFormatter.ISO_TIME));
    System.out.println(findnum + "Ist" + newlist.size() + "Es gab einen!");
  }
Ausführungsergebnis

Ausführungsergebnis


Während der Testdatengenerierung...

--- byList ---
start: 2018-12-08T15:35:51.584
end  : 2018-12-08T15:35:52.039
elapsed: 00:00:00.455
Es waren 1500072 99!

--- byStream ---
start: 2018-12-08T15:35:52.052
end  : 2018-12-08T15:35:52.450
elapsed: 00:00:00.398
Es waren 1500072 99!

--- byParalellStream ---
start: 2018-12-08T15:35:52.450
end  : 2018-12-08T15:35:52.672
elapsed: 00:00:00.222
Es waren 1500072 99!

Bestätigen Sie, dass die Reihenfolge von forEach und findAny nicht garantiert ist

Mit parallelStream war dies sicherlich nicht garantiert. In Sequential Stream wurde in der Reihenfolge der Originalquelle (Liste) darauf zugegriffen.

source

python


    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    System.out.println("--- byList ---");
    for (int i : list) {
      System.out.println(i);
    }

    System.out.println("--- byStream ---");
    list.stream().forEach(i -> System.out.println(i));

    System.out.println("--- byParallelStream ---");
    list.parallelStream().forEach(i -> System.out.println(i));

    System.out
        .println("findany by stream:" + list.stream().findAny().orElse(null));

    System.out.println("findany by parallelStream:"
        + list.parallelStream().findAny().orElse(null));
Ausführungsergebnis

Ausführungsergebnis


--- byList ---
1
2
3
4
5
6
7
8
9
10
--- byStream ---
1
2
3
4
5
6
7
8
9
10
--- byParallelStream ---
7
9
6
3
5
2
10
1
4
8
findany by stream:1
findany by parallelStream:7

Verwirrter Punkt

Argumente für jede Methode in der Stream-Schnittstelle

Es wird eine funktionale Schnittstelle (Verhalten) als Argument anstelle von Daten übergeben. Dies nennt man funktionale Programmierung. Ich konnte es nicht einfach schreiben, weil ich es nur prozedural geschrieben habe.

Ich vergesse es bald und kann es nicht auf einmal schreiben. Anstatt einen Lambda-Ausdruck zu verwenden, habe ich eine anonyme Klasse mit der neuen Schnittstelle () {...} erstellt, eine abstrakte Methode implementiert und durch einen Lambda-Ausdruck ersetzt .. Ich schäme mich zu sagen ... Nun, Sie werden sich bald daran gewöhnen.

Artikel, die ich als Referenz verwendet habe

Vielen Dank an alle Autoren!

Grundlagen der Stream-API https://qiita.com/Takmiy/items/f1d44dfde0d3a906d321

Übersicht über Java 8-Funktion, Verbraucher, Lieferant, Prädikat https://qiita.com/subaru44k/items/c55d9b9fc419f0d09c64

Was ist funktionale Programmierung und was ist Lambda? https://qiita.com/lrf141/items/98ffbeaee42d30cca4dc

Unterschied zwischen Stream Map und FlatMap https://qiita.com/KevinFQ/items/97137efb2159009b60e1

Außerhalb von Qiita. Es beschreibt vom Zweck der Stream-API bis zu den experimentellen Ergebnissen. http://d.hatena.ne.jp/nowokay/20130506

Recommended Posts

Probieren Sie verschiedene Java Stream API-Methoden aus (jetzt)
Java 8 ~ Stream API ~ startet jetzt
Probieren Sie Java 8 Stream aus
Java Stream API
Versuchen Sie es mit der Stream-API in Java
Java Stream API Spickzettel
Java Stream API in 5 Minuten
[Java] Stream API - Stream-Beendigungsverarbeitung
[Java] Stream API - Stream Zwischenverarbeitung
[Java] Einführung in die Stream-API
[Java] Stream API Zwischenoperation
[swift5] Versuchen Sie, einen API-Client auf verschiedene Arten zu erstellen
Verschiedene Methoden der Java String Klasse
[java8] Um die Stream-API zu verstehen
[Einführung in Java] Informationen zur Stream-API
Ich habe versucht, die Java8 Stream API zu verwenden
Java-Methoden
Java-Methoden
Datenverarbeitung mit der Stream-API von Java 8
Heutzutage Java Lambda Expressions und Stream API
Versuchen Sie es mit der JSON-Format-API in Java
Java 8 startet jetzt ~ Datums- und Uhrzeit-API ~
API-Memo streamen
Versuchen Sie, die Cloud Vision-API von GCP in Java zu verwenden
Java 8 studieren (Stream)
Versuchen Sie es mit der Syntaxanalyse der COTOHA-API in Java
Versuchen Sie es mit Java 9
Java Stream-Beendigung
[Java] Stream-Verarbeitung
Grundlagen der Stream-API
Java 9 Optional :: stream
Versuchen Sie, synchronisierte Methoden aus mehreren Threads in Java aufzurufen
[Inhouse-Lernsitzung] Java-Grundlagen - Lambda-Ausdruck und Stream-API - (13.07.2017)
[Für Anfänger] So bedienen Sie die Stream-API nach Java 8
Verwenden Sie Java-Lambda-Ausdrücke außerhalb der Stream-API
[Java] Stream Collectors Hinweis
Packen Sie die API-Antwort (Java)
Versuchen Sie es mit der Methode java.lang.Math
[Java] Stream API-Stream-Generierung
Stream-API (Collectors-Klasse)
Stream-API-Zuordnungsmethode
Fehlerbehebung bei der Docker-Client Java API
Verschiedene Threads in Java
Zabbix API in Java
Informationen zur Java8-Stream-Reduzierung
Überprüfen Sie jetzt die Java-Anmerkungen
Java zufällig, verschiedene Verarbeitung
Versuchen Sie es mit dem Java-Rückgabewert
Grobe Zusammenfassung des Java8-Streams
Behandeln Sie Ausnahmen kühl mit Java 8-Lambda-Ausdrücken und der Stream-API
Ich möchte die Java 8 DateTime-API (jetzt) langsam verwenden.
Jetzt ist es an der Zeit, mit der Stream-API zu beginnen
Konvertieren Sie ein zweidimensionales Array mit der Java 8 Stream-API in das CSV-Format