Java 8 ~ Stream API ~ pour commencer maintenant

Dernière fois: Java8 pour démarrer maintenant ~ for Each et expression lambda ~

Vient ensuite l'édition Stream API.

Qu'est-ce que l'API Stream?

Il s'agit d'une API introduite à partir de Java8 qui peut décrire le traitement (opération d'agrégation) des tableaux et des collections. Suivez la procédure ci-dessous pour un ensemble d'éléments.

  1. Génération: générez un flux à partir d'un tableau, d'une collection, d'un fichier, etc.
  2. Opération intermédiaire: extraire, trier et traiter les valeurs pour Stream en spécifiant des conditions.
  3. Opération de terminaison: convertir du flux en collection, agréger, obtenir la valeur maximale / minimale, etc. L'opération de terminaison ne peut être effectuée qu'une seule fois pour un flux.

C'est complètement différent de la façon d'écrire vers Java7, je vais donc le résumer à l'aide d'un exemple.

exemple

Spécifications du fichier d'entrée

Commun

Dossier de commande

order.csv


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

Maître de nom de produit

item.csv


BBJ001,Stylo bille noir
BBJ005,Stylo bille rouge
AES010,la gomme

Spécifications du fichier de sortie

order_collected.csv


DIH999,,10
BBJ005,Stylo bille rouge,100
BBJ001,Stylo bille noir,300
BBJ001,Stylo bille noir,50
AES010,la gomme,20
AES010,la gomme,150

procédure

Si vous déposez cet exemple dans votre code, je pense que ce serait comme ça.

  1. Lisez la fiche de nom de produit
  2. Divisez une ligne en code produit et nom de produit
  3. clé: code produit, valeur: carte du nom du produit
  4. Lisez le fichier de commande
  5. Trier les fichiers de commande par code produit
  6. Renseignez le nom de produit du fichier de commande à partir de la carte de la fiche de nom de produit.
  7. Sortie dans un fichier

Implémentation avec l'API Stream

** Étape 1. Chargez le nom de produit maître **

Stream <String> java.nio.file.Files # lines (Path) pour générer un Stream avec toutes les lignes du fichier. Avant Java7, Reader etc. étaient générés et lus un par un.

Lecture de fichiers de la version Java 7


BufferedReader reader = new BufferedReader(new FileReader("files/stream/item.csv"));
String line = null;
while ((line = reader.readLine()) != null) {
    //Traitement divers pour une ligne
}

Maintenant ça.

Lecture du fichier de version de l'API Stream


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

** Procédure 2. Décomposez une ligne en code produit et nom de produit **

Décomposez chaque élément du Stream créé à l'étape précédente.

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

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

L'opération intermédiaire map '' renvoie le Stream résultant de l'application de l'argument expression lambda à chaque élément du Stream. Cette fois, nous passons l'expression lambda line-> line.split (",") ``.

Traitez line.split (",") pour chaque élément line de Stream <String> itemStream et flux de type Stream <String []> A été généré.

BBJ001,Stylo bille noir// ⇒ [BBJ001,Stylo bille noir]
BBJ005,Stylo bille rouge// ⇒ [BBJ005,Stylo bille rouge]
・ ・ ・

L'important est que les ** opérations intermédiaires de flux renvoient Stream **. Les opérations intermédiaires et les opérations de terminaison peuvent être effectuées sur les résultats des opérations intermédiaires.

** Étape 3. Légende: code produit, valeur: carte du nom du produit (carte produit) **

Comme il est difficile de gérer le Stream tel qu'il figure dans l'attribution du nom de produit dans la procédure ultérieure, convertissez-le en 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)

L'opération de terminaison collect '' renvoie le résultat de l'application d'une certaine règle (Collector) à chaque élément de Stream. Les règles fréquemment utilisées sont disponibles dans [ Collectors``](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Collectors.html).

Ici, le collecteur toMap (<expression Lambda qui crée une clé de carte>, <expression Lambda qui crée une valeur de carte>) qui renvoie une carte est utilisé.

Puisque itemStream2 est un Stream de `` String [] '', nous avons généré une carte avec le 0e élément du tableau comme clé et le 1er élément comme valeur.

Résumé principal du nom du produit

** Opérations intermédiaires de Stream return Stream **, vous pouvez donc écrire dans une chaîne de la création du Stream à la conversion de la carte.

//Lire le fichier de nom de produit
Map<String, String> items = Files.lines(Paths.get("files/stream/item.csv") // Stream<String>
	//Convertir une ligne de fichier en tableau(Préparation de la carte)
	.map(line -> line.split(","))                                      // Stream<String[]>
	//Convertir en carte
	.collect(Collectors.toMap(item -> item[0], item -> item[1]));      // Map<String, String>

** Étape 4. Lire (générer) le fichier de commande **

Ensuite, nous commencerons le traitement du fichier de commande. C'est le même que le nom de produit maître jusqu'au point où une ligne de données est décomposée.

Stream<String> orderStream = Files.lines(Paths.get("files/stream/order.csv"))
Stream<OrderDto> orderStream2 = orderStream
				//Convertir une ligne de fichier en tableau(Préparation au Dto)
				.map(line -> line.split(","))
				//Convertir le tableau en Dto de livraison
				.map(array -> makeOrder(array));

Après la séparation avec ",", je l'ai mappé à OrderDto avec makeOrder (String []).

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;
}

** Étape 5. Trier les fichiers de commande par code produit (opération intermédiaire) **

Trier par ordre croissant du code produit.

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

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

Comparator définit les règles de comparaison entre les objets C'est une interface fonctionnelle. Si vous implémentez l'interface Comparable, elle n'a pas d'arguments` Vous pouvez également utiliser `` sorted () ''.

Vous pouvez définir un ordre de tri par défaut dans l'interface Comparable '' et le redéfinir de manière concise dans une expression lambda en utilisant Comparator '' si nécessaire.

** Étape 6. Renseignez le nom de produit du fichier de commande à partir de la carte principale des noms de produits (opération intermédiaire) **

Recherchez dans la carte des produits par code de produit, et si cela correspond, indiquez le nom du produit et, s'il ne correspond pas, remplissez les caractères vides.

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

Utilisez à nouveau la carte. Facultatif n'est pas expliqué en détail ici, mais il est utilisé comme fonction pour déterminer la valeur par défaut lorsqu'elle est Null.

** Étape 7. Sortie dans un fichier (opération de terminaison) **

Maintenant que les données sont complètes, exportez-les dans un fichier.

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)

L'opération de terminaison `` forEach '' utilisée dans l'explication de l'expression lambda la dernière fois exécute l'opération spécifiée par l'argument pour chaque élément.

Achevée

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"))){

			//Lire le fichier de commande
			Map<String, String> items = itemStream
					//Convertir une ligne de fichier en tableau(Préparation de la carte)
					.map(line -> line.split(","))
					//Convertir en carte
					.collect(Collectors.toMap(item -> item[0], item -> item[1]));

			//Lire le fichier de nom de produit
			Stream<OrderDto> orderList = orderStream
				//Convertir une ligne de fichier en tableau(Préparation au Dto)
				.map(line -> line.split(","))
				//Convertir le tableau en Dto de livraison
				.map(array -> makeOrder(array))
				//Trier
				.sorted((item1, item2) -> item1.getItemCode().compareTo(item2.getItemCode()))
				//correspondant à
				.map(order -> {
					order.setItemName(Optional.ofNullable(items.get(order.getItemCode())).orElse(""));
					return order;
				});

			//production
			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;
	}
}

Qu'est-ce que l'API Re: Stream?

En résolvant l'exemple, j'ai d'abord organisé la procédure.

  1. Lire la fiche produit
  2. Divisez une ligne en code produit et nom de produit
  3. clé: code produit, valeur: carte du nom du produit

Probablement, dans le code Java7 ou antérieur, même la carte est générée au moment de la boucle for pour lire le nom de produit principal.

Java7


for (/*Ensemble d'éléments*/) {
    //Traitement divers pour un élément
}

À propos, l'API Stream fonctionne sur un ensemble d'éléments. Les opérations typiques sont map '' (convertir un élément en un autre élément), filter '' (extraire celui qui remplit les conditions des éléments / inutilisé cette fois), `` trié '' Par exemple, `(éléments de tri). De plus, comme la valeur de retour de l'opération intermédiaire est Stream, il convient de créer d'abord un ensemble d'éléments puis de fonctionner en continu.

Java8


Stream obj = //Convertir un ensemble d'éléments en Stream
  //Conversion d'éléments dans obj
  .map(/*Règles de conversion*/)
  //Filtration
  .filter(/*Règles d'extraction*/);

Lors de l'utilisation de l'API Stream, il semble que vous deviez penser à la procédure afin qu'elle soit une combinaison d'opérations simples sur les éléments.

L'article suivant a été très utile. Écrire du code de type Java8 en Java8

prime

Je voulais trouver la quantité totale de commande pour chaque code produit, mais j'ai abandonné car je ne savais pas comment l'écrire correctement. Je vais laisser le code commémoratif pour la version forcée, alors faites-le moi savoir si vous avez de bonnes idées.

//Lire le fichier de nom de produit
Stream<OrderDto> orderList = orderStream
	//Convertir une ligne de fichier en tableau(Préparation au Dto)
	.map(line -> line.split(","))
	//Convertir le tableau en Dto de livraison
	.map(array -> makeOrder(array));

//Regrouper par code produit pour l'agrégation
Map<String, List<OrderDto>> grouping = orderList.collect(Collectors.groupingBy(order->order.getItemCode()));
//Additionner la quantité commandée pour chaque élément groupé
orderList = grouping.values()
		.stream()
		.map(orders->{
			//Ramassez l'un des éléments
			OrderDto order = orders.stream().findAny().get();
			//Stocker le nombre total de tous les éléments dans la quantité commandée
			order.setOrderNum(orders.stream().mapToInt(oo ->oo.getOrderNum()).sum());
			return order;
		})
		//Trier
		.sorted((item1, item2) -> item1.getItemCode().compareTo(item2.getItemCode()))
		//Définir le nom du produit
		.map(order -> {
			order.setItemName(Optional.ofNullable(items.get(order.getItemCode())).orElse(""));
			return order;
		});

Recommended Posts

Java 8 ~ Stream API ~ pour commencer maintenant
Java 8 pour démarrer maintenant ~ API de date et d'heure ~
[Java] Introduction à l'API Stream
Java8 pour démarrer maintenant ~ Facultatif ~
[java8] Pour comprendre l'API Stream
[Introduction à Java] À propos de l'API Stream
API Java Stream
Essayez différentes méthodes d'API Java Stream (maintenant)
[Java] API / carte de flux
Pratique de l'API Java8 Stream
Java 8 pour démarrer maintenant ~ for Each et expression lambda ~
Aide-mémoire de l'API Java Stream
API Java Stream en 5 minutes
[Java] Stream API - Traitement de l'arrêt du flux
[Java] Stream API - Traitement intermédiaire de flux
[Java] Opération intermédiaire de l'API Stream
[À voir absolument pour l'apprenti ingénieur Java] Comment utiliser l'API Stream
J'ai essayé d'utiliser l'API Java8 Stream
Java, interface pour partir du débutant
Il est maintenant temps de commencer avec l'API Stream
Java, des tableaux pour débuter avec les débutants
J'ai essayé de résumer Java 8 maintenant
Convertir un tableau bidimensionnel au format csv avec l'API Java 8 Stream
Traitement des données à l'aide de l'API de flux de Java 8
Essayez d'utiliser l'API Stream en Java
De nos jours, les expressions Java Lambda et l'API de flux
Classe anonyme (visant à introduire l'API de flux)
J'ai essayé de résumer l'API Stream
Mémo API Stream
Essayez Java 8 Stream
[Java] Introduction à Java
Étudier Java 8 (Stream)
Introduction à Java
Terminaison du flux Java
[Java] Traitement de flux
Principes de base de l'API Stream
Java 9 Facultatif :: stream
Java8 / 9 Beginners: Streaming API addiction points et comment les gérer
Deux façons de démarrer un thread en Java + @
Comment utiliser l'API Java avec des expressions lambda
Fonctionnalités susceptibles d'entrer dans Java 10 pour le moment
Traitement des listes à comprendre avec des images - java8 stream / javaslang-
Exemple de code pour convertir List en List <String> dans Java Stream
Changements de Java 8 à Java 11
Somme de Java_1 à 100
[Java] Remarque sur les collecteurs de flux
[Session d'étude interne] Principes de base de l'expression Java-Lambda et de l'API Stream- (13/07/2017)
API Stream (classe Collectors)
[Java] Connectez-vous à MySQL
Utiliser des expressions Java lambda en dehors de l'API Stream
Méthode de mappage de l'API Stream
Améliorations de Kotlin à Java
De Java à Ruby !!
API Zabbix en Java
À propos de l'opération de réduction du flux Java8
Résumé de l'API de communication Java (1) Comment utiliser Socket
Consultez les annotations Java maintenant
Résumé de l'API de communication Java (3) Comment utiliser SocketChannel