Java 8 ~ Stream API ~ startet jetzt

Letztes Mal: Java 8 ~ für jeden und Lambda-Ausdruck ~

Als nächstes folgt die Stream API Edition.

Was ist die Stream-API?

Es handelt sich um eine von Java8 eingeführte API, die die Verarbeitung (Aggregationsoperation) für Arrays und Sammlungen beschreiben kann. Befolgen Sie die nachstehenden Anweisungen für eine Reihe von Elementen.

  1. Generierung: Generieren Sie einen Stream aus einem Array, einer Sammlung, einer Datei usw.
  2. Zwischenoperation: Extrahieren, sortieren und verarbeiten Sie Werte für Stream, indem Sie Bedingungen angeben.
  3. Beendigungsvorgang: Von Stream in Sammlung konvertieren, aggregieren, Maximal- / Minimalwert abrufen usw. Der Beendigungsvorgang kann nur einmal für einen Stream ausgeführt werden.

Es ist völlig anders als das Schreiben in Java7, daher fasse ich es anhand eines Beispiels zusammen.

Beispiel

Angaben zur Eingabedatei

Verbreitet

Bestelldatei

--Dateienartikel sind "Produktcode, Bestellmenge"

order.csv


BBJ001,300
AES010,20
BBJ005,100
BBJ001,50
DIH999,10
AES010,150

Produktname Master

--Dateielemente sollten "Produktcode, Produktname" sein.

item.csv


BBJ001,Kugelschreiber schwarz
BBJ005,Kugelschreiber rot
AES010,Radiergummi

Spezifikationen der Ausgabedatei

order_collected.csv


DIH999,,10
BBJ005,Kugelschreiber rot,100
BBJ001,Kugelschreiber schwarz,300
BBJ001,Kugelschreiber schwarz,50
AES010,Radiergummi,20
AES010,Radiergummi,150

Verfahren

Wenn Sie dieses Beispiel in Ihren Code einfügen, würde es meiner Meinung nach so aussehen.

  1. Lesen Sie den Produktnamenstamm
  2. Teilen Sie eine Zeile in Produktcode und Produktnamen auf
  3. Schlüssel: Produktcode, Wert: Karte des Produktnamens
  4. Lesen Sie die Bestelldatei
  5. Sortieren Sie die Bestelldateien nach Produktcode
  6. Geben Sie den Produktnamen der Bestelldatei aus der Karte des Produktnamenstamms ein.
  7. Ausgabe in Datei

Implementierung mit Stream API

** Schritt 1. Laden Sie den Produktnamenstamm **

Stream <String> java.nio.file.Files # lines (Path), um einen Stream mit allen Zeilen in der Datei zu generieren. Vor Java7 wurden Reader usw. einzeln generiert und gelesen.

Lesen der Java 7-Versionsdatei


BufferedReader reader = new BufferedReader(new FileReader("files/stream/item.csv"));
String line = null;
while ((line = reader.readLine()) != null) {
    //Verschiedene Verarbeitung für eine Zeile
}

Jetzt das.

Lesen der Stream-API-Versionsdatei


Stream<String> itemStream = Files.lines(Paths.get("files/stream/item.csv"));

** Vorgehensweise 2. Teilen Sie eine Zeile in Produktcode und Produktnamen auf **

Zerlegen Sie jedes Element des Streams, das im vorherigen Schritt erstellt wurde.

Stream<String[]> itemStream2 = itemStream .map(line -> line.split(","));

<R> Stream<R> map(Function<? super T,? extends R> mapper)

Die Zwischenoperation map gibt den Stream zurück, der sich aus der Anwendung des Argument-Lambda-Ausdrucks auf jedes Element des Streams ergibt. Dieses Mal übergeben wir den Lambda-Ausdruck line-> line.split (",").

Verarbeiten Sie line.split (",") für jedes Element line von Stream <String> itemStream und Stream vom Typ Stream <String []> Wurde generiert.

BBJ001,Kugelschreiber schwarz// ⇒ [BBJ001,Kugelschreiber schwarz]
BBJ005,Kugelschreiber rot// ⇒ [BBJ005,Kugelschreiber rot]
・ ・ ・

Wichtig ist, dass ** Stream-Zwischenoperationen Stream ** zurückgeben. Zwischenoperationen und Beendigungsoperationen können mit den Ergebnissen von Zwischenoperationen durchgeführt werden.

** Schritt 3. Schlüssel: Produktcode, Wert: Karte des Produktnamens (Produktkarte) **

Da es schwierig ist, den Stream so zu behandeln, wie er in der späteren Zuweisung des Produktnamens angegeben ist, konvertieren Sie ihn in Map.

Map<String, String> items = itemStream2.collect(Collectors.toMap(item -> item[0], item -> item[1]));

<R,A> R collect(Collector<? super T,A,R> collector)

Die Beendigungsoperation collect gibt das Ergebnis der Anwendung einer bestimmten Regel (Collector) auf jedes Element von Stream zurück. Häufig verwendete Regeln sind in [ Collectors] verfügbar (https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Collectors.html).

Hier wird Collector toMap (<Lambda-Ausdruck, der einen Map-Schlüssel erstellt>, <Lambda-Ausdruck, der einen Map-Wert erstellt>) verwendet, der eine Map zurückgibt.

Da itemStream2 ein Stream von String [] ist, haben wir eine Map mit dem 0. Element des Arrays als Schlüssel und dem 1. Element als Wert generiert.

Produktname Master-Zusammenfassung

** Zwischenoperationen von Stream geben Stream zurück **, sodass Sie in einer Kette von der Stream-Erstellung bis zur Map-Konvertierung schreiben können.

//Produktnamensdatei lesen
Map<String, String> items = Files.lines(Paths.get("files/stream/item.csv") // Stream<String>
	//Konvertieren Sie eine Dateizeile in ein Array(Vorbereitung für die Karte)
	.map(line -> line.split(","))                                      // Stream<String[]>
	//In Karte konvertieren
	.collect(Collectors.toMap(item -> item[0], item -> item[1]));      // Map<String, String>

** Schritt 4. Lesen (generieren) Sie die Bestelldatei **

Als nächstes beginnen wir mit der Verarbeitung der Bestelldatei. Es ist bis zum Punkt, an dem eine Datenzeile zerlegt wird, dasselbe wie der Produktnamenstamm.

Stream<String> orderStream = Files.lines(Paths.get("files/stream/order.csv"))
Stream<OrderDto> orderStream2 = orderStream
				//Konvertieren Sie eine Dateizeile in ein Array(Vorbereitung für Dto)
				.map(line -> line.split(","))
				//Array in Delivery Dto konvertieren
				.map(array -> makeOrder(array));

Nach dem Teilen mit "," habe ich OrderDto mit makeOrder (String []) zugeordnet.

private static OrderDto makeOrder(String[] array) {
	OrderDto order = new OrderDto();
	int idx = 0;
	order.setItemCode(array[idx++]);
	order.setOrderNum(Integer.parseInt(array[idx++]));
	return order;
}

** Schritt 5. Bestelldateien nach Produktcode sortieren (Zwischenoperation) **

Sortieren nach aufsteigender Reihenfolge des Produktcodes.

Stream<OrderDto> orderStream3 = orderStream2.sorted((item1, item2) -> item1.getItemCode().compareTo(item2.getItemCode()));

Stream<T> sorted(Comparator<? super T> comparator)

Comparator definiert Vergleichsregeln zwischen Objekten Es ist eine funktionale Schnittstelle. Wenn Sie die Schnittstelle Comparable implementieren, hat sie keine ArgumenteSie können auchsortiert () verwenden.

Sie können eine Standardsortierreihenfolge in der Schnittstelle Comparable festlegen und diese bei Bedarf mit Comparator in einem Lambda-Ausdruck präzise neu definieren.

** Schritt 6. Geben Sie den Produktnamen der Bestelldatei aus der Produktnamen-Master-Map ein (Zwischenoperation) **

Durchsuchen Sie die Produktkarte nach Produktcode. Wenn dies der Fall ist, geben Sie den Produktnamen ein. Wenn dies nicht der Fall ist, geben Sie die Leerzeichen ein.

Stream<OrderDto> orderStream4 = orderStream2.map(order -> {
					order.setItemName(Optional.ofNullable(items.get(order.getItemCode())).orElse(""));
					return order;
				});

Verwenden Sie die Karte erneut. Optional wird hier nicht im Detail erläutert, es wird jedoch als Funktion verwendet, um den Standardwert zu bestimmen, wenn er Null ist.

** Schritt 7. Ausgabe in Datei (Beendigungsvorgang) **

Nachdem die Daten vollständig sind, geben Sie sie in eine Datei aus.

try (BufferedWriter writer = new BufferedWriter(new FileWriter("files/stream/order_collected.csv")) ) {
	orderList.forEach(order -> {
		try {
			writer.write(makeLine(order));
			writer.newLine();
		} catch (IOException e) {e.printStackTrace();return;}
	});
}

void forEach(Consumer<? super T> action)

Die in der vorherigen Erläuterung des Lambda-Ausdrucks verwendete Beendigungsoperation forEach führt die durch das Argument für jedes Element angegebene Operation aus.

Komplett

public class StreamMain {

	public static void main(String[] args) {
		try (Stream<String> orderStream = Files.lines(Paths.get("files/stream/order.csv"));
				Stream<String> itemStream = Files.lines(Paths.get("files/stream/item.csv"))){

			//Bestelldatei lesen
			Map<String, String> items = itemStream
					//Konvertieren Sie eine Dateizeile in ein Array(Vorbereitung für die Karte)
					.map(line -> line.split(","))
					//In Karte konvertieren
					.collect(Collectors.toMap(item -> item[0], item -> item[1]));

			//Produktnamensdatei lesen
			Stream<OrderDto> orderList = orderStream
				//Konvertieren Sie eine Dateizeile in ein Array(Vorbereitung für Dto)
				.map(line -> line.split(","))
				//Array in Delivery Dto konvertieren
				.map(array -> makeOrder(array))
				//Sortieren
				.sorted((item1, item2) -> item1.getItemCode().compareTo(item2.getItemCode()))
				//passend
				.map(order -> {
					order.setItemName(Optional.ofNullable(items.get(order.getItemCode())).orElse(""));
					return order;
				});

			//Ausgabe
			try (BufferedWriter writer = new BufferedWriter(new FileWriter("files/stream/order_collected.csv")) ) {
				orderList.forEach(order -> {
					try {
						writer.write(makeLine(order));
						writer.newLine();
					} catch (IOException e) {e.printStackTrace();return;}
				});
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static String makeLine(OrderDto order) {
		StringBuilder line = new StringBuilder();
		line.append(order.getItemCode());
		line.append(',');
		line.append(order.getItemName());
		line.append(',');
		line.append(order.getOrderNum());
		return line.toString();
	}

	private static OrderDto makeOrder(String[] array) {
		OrderDto order = new OrderDto();
		int idx = 0;
		order.setItemCode(array[idx++]);
		order.setOrderNum(Integer.parseInt(array[idx++]));
		return order;
	}
}

Was ist die Re: Stream-API?

Bei der Lösung des Beispiels habe ich zuerst die Prozedur organisiert.

  1. Lesen Sie den Produktnamenstamm
  2. Teilen Sie eine Zeile in Produktcode und Produktnamen auf
  3. Schlüssel: Produktcode, Wert: Karte des Produktnamens

Wahrscheinlich wird in Java7 oder früherem Code zum Zeitpunkt der for-Schleife sogar Map generiert, um den Produktnamenstamm zu lesen.

Java7


for (/*Satz von Elementen*/) {
    //Verschiedene Verarbeitung für ein Element
}

Die Stream-API arbeitet übrigens mit einer Reihe von Elementen. Typische Operationen sind map (konvertiere ein Element in ein anderes Element), filter (extrahiere diejenige, die die Bedingungen aus den Elementen erfüllt / diesmal nicht verwendet), `` sortiertZum Beispiel(Elemente sortieren). Da der Rückgabewert der Zwischenoperation Stream ist, ist es außerdem geeignet, zuerst einen Satz von Elementen zu erstellen und dann kontinuierlich zu arbeiten.

Java8


Stream obj = //Konvertieren Sie eine Reihe von Elementen in Stream
  //Elemente in obj konvertieren
  .map(/*Konvertierungsregeln*/)
  //Filtern
  .filter(/*Extraktionsregeln*/);

Wenn Sie die Stream-API verwenden, sollten Sie über die Prozedur nachdenken, damit es sich um eine Kombination einfacher Operationen an den Elementen handelt.

Der folgende Artikel war sehr hilfreich. Java8-ähnlichen Code in Java8 schreiben

Bonus

Ich wollte die Gesamtbestellmenge für jeden Produktcode ermitteln, gab jedoch auf, weil ich nicht herausfinden konnte, wie ich sie gut schreiben sollte. Ich werde den Gedenkcode der Version hinterlassen, die ich erzwungen habe. Bitte lassen Sie mich wissen, wenn Sie gute Hände haben.

//Produktnamensdatei lesen
Stream<OrderDto> orderList = orderStream
	//Konvertieren Sie eine Dateizeile in ein Array(Vorbereitung für Dto)
	.map(line -> line.split(","))
	//Array in Delivery Dto konvertieren
	.map(array -> makeOrder(array));

//Gruppieren nach Produktcode für die Aggregation
Map<String, List<OrderDto>> grouping = orderList.collect(Collectors.groupingBy(order->order.getItemCode()));
//Summieren Sie die Bestellmenge für jedes gruppierte Element
orderList = grouping.values()
		.stream()
		.map(orders->{
			//Nimm eines der Elemente auf
			OrderDto order = orders.stream().findAny().get();
			//Speichern Sie die Gesamtzahl aller Elemente in der Bestellmenge
			order.setOrderNum(orders.stream().mapToInt(oo ->oo.getOrderNum()).sum());
			return order;
		})
		//Sortieren
		.sorted((item1, item2) -> item1.getItemCode().compareTo(item2.getItemCode()))
		//Stellen Sie den Produktnamen ein
		.map(order -> {
			order.setItemName(Optional.ofNullable(items.get(order.getItemCode())).orElse(""));
			return order;
		});

Recommended Posts

Java 8 ~ Stream API ~ startet jetzt
Java 8 startet jetzt ~ Datums- und Uhrzeit-API ~
[Java] Einführung in die Stream-API
Java8 startet jetzt ~ Optional ~
[java8] Um die Stream-API zu verstehen
[Einführung in Java] Informationen zur Stream-API
Java Stream API
Probieren Sie verschiedene Java Stream API-Methoden aus (jetzt)
[Java] Stream API / Map
Java 8 startet jetzt ~ für jeden und Lambda-Ausdruck ~
Java Stream API Spickzettel
Java Stream API in 5 Minuten
[Java] Stream API - Stream-Beendigungsverarbeitung
[Java] Stream API - Stream Zwischenverarbeitung
[Java] Stream API Zwischenoperation
[Ein Muss für einen Java-Ingenieurlehrling] Verwendung der Stream-API
Ich habe versucht, die Java8 Stream API zu verwenden
Java, Schnittstelle für Anfänger
Jetzt ist es an der Zeit, mit der Stream-API zu beginnen
Java, Arrays für Anfänger
Ich habe jetzt versucht, Java 8 zusammenzufassen
Konvertieren Sie ein zweidimensionales Array mit der Java 8 Stream-API in das CSV-Format
Datenverarbeitung mit der Stream-API von Java 8
Versuchen Sie es mit der Stream-API in Java
Heutzutage Java Lambda Expressions und Stream API
Anonyme Klasse (mit dem Ziel, Stream-API einzuführen)
Ich habe versucht, die Stream-API zusammenzufassen
API-Memo streamen
Probieren Sie Java 8 Stream aus
[Java] Einführung in Java
Java 8 studieren (Stream)
Einführung in Java
Java Stream-Beendigung
[Java] Stream-Verarbeitung
Grundlagen der Stream-API
Java 9 Optional :: stream
Java8 / 9-Anfänger: Streamen Sie API-Suchtpunkte und wie Sie damit umgehen
Zwei Möglichkeiten, einen Thread in Java + @ zu starten
Verwendung der Java-API mit Lambda-Ausdrücken
Funktionen, die derzeit wahrscheinlich in Java 10 eingegeben werden
Listenverarbeitung zum Verstehen mit Bildern --java8 stream / javaslang-
Beispielcode zum Konvertieren von List in List <String> in Java Stream
Änderungen von Java 8 zu Java 11
Summe von Java_1 bis 100
[Java] Stream Collectors Hinweis
[Inhouse-Lernsitzung] Java-Grundlagen - Lambda-Ausdruck und Stream-API - (13.07.2017)
Stream-API (Collectors-Klasse)
[Java] Stellen Sie eine Verbindung zu MySQL her
Verwenden Sie Java-Lambda-Ausdrücke außerhalb der Stream-API
Stream-API-Zuordnungsmethode
Kotlins Verbesserungen an Java
Von Java zu Ruby !!
Zabbix API in Java
Informationen zur Java8-Stream-Reduzierung
Zusammenfassung der Java-Kommunikations-API (1) Verwendung von Socket
Überprüfen Sie jetzt die Java-Anmerkungen
Zusammenfassung der Java-Kommunikations-API (3) Verwendung von SocketChannel