Un moyen simple de créer une implémentation de java.util.stream.Stream

Motivation

L'idiome typique pour traiter les sous-chaînes qui correspondent à une expression régulière à l'aide de java.regex.Matcher est:

Pattern pattern = Pattern.compile("(cola)+");
Matcher matcher = pattern.matcher("cola, cola, I love cola.");
while (mather.find()) {
  // do something with the current match.
  System.err.println(matcher.group());
}

Si vous souhaitez simplement effectuer un traitement en lecture seule pour la partie correspondante, vous devriez pouvoir l'écrire en tant que traitement de flux. Comme ça.

Matcher matcher = pattern.matcher("cola, cola, I love cola.");
matcher.forEach(h -> System.err.println(h.group()); //h est quelque chose qui représente une correspondance (doit être défini)

Il était bon de penser que cela pouvait être réalisé en créant une implémentation de java.util.stream.Stream qui encapsule Matcher, mais c'est difficile à implémenter car il y a trop d'interfaces et de méthodes. https://docs.oracle.com/javase/jp/9/docs/api/java/util/stream/Stream.html Existe-t-il un moyen simple d'implémenter Stream?

Addendum: Solution pour Matcher

L'article original listait les solutions générales ci-dessous, mais pour Matcher, vous pouvez obtenir la réponse complète en utilisant Matcher # results () de Java 9. La mise en œuvre de cette méthode implémente exactement ce que j'ai écrit ci-dessus.

Pattern pattern = Pattern.compile("(cola)+");
pattern.matcher("cola, cola, I love cola.").results()
    .forEach(x -> System.err.println(x.group()));

REMARQUE: Merci à @ saka1029 pour l'avoir signalé. De plus, veuillez vous référer à ce qui suit pour la méthode générale de vouloir itérer autre chose que «Matcher».

Solution commune

À la suite d'un peu de recherche, il a été trouvé que ce qui suit peut être écrit en combinant StreamSupport # stream et Spliterators # spliteratorUnknownSize. Comme vous pouvez le voir, cette méthode peut être appliquée non seulement à Matcher mais aussi à l'implémentation de java.util.Iterator. C'est pourquoi il est si polyvalent que je vais en prendre note. [Ajout: je comprends que cet exemple seul est plus long et plus compliqué que le code original :-)]

RegExTest.java


import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 
 */
public class RegExTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		
		final Pattern pattern = Pattern.compile("(cola)+");

		final Stream<Matcher> s = StreamSupport.stream(
			Spliterators.spliteratorUnknownSize(
				new Iterator<Matcher>() {
					final Matcher matcher = pattern.matcher("cola, cola, I love cola.");
					@Override
					public boolean hasNext() {
						return matcher.find();
					}
					@Override
					public Matcher next() {
						return matcher;
					}
				},
				Spliterator.NONNULL | Spliterator.IMMUTABLE),
			false);
		
		//Vous pouvez maintenant l'utiliser de la même manière que l'exemple du début!
		s.forEach(m -> System.err.println(m.group()));
	}

}

Addendum: Comment éviter d'implémenter java.util.Iterator

@ saka1029 a de nouveau souligné, la méthode Stream # iterate fournie par Java9 de java.util.stream.Stream. En utilisant api / java / util / stream / Stream.html # iterate (T, java.util.function.Predicate, java.util.function.UnaryOperator)), c'est beau sans implémenter ʻIterator` comme indiqué ci-dessous. J'ai appris que je peux écrire. Merci, @ saka1029. Je suis heureux que Java9 ait fourni cette nouvelle façon d'écrire, car il y aurait eu beaucoup de personnes autres que moi qui auraient souhaité pouvoir l'écrire comme ça.

final Pattern pattern = Pattern.compile("(cola)+");
Stream.iterate(pattern.matcher("cola, cola, I love cola."), m -> m.find(), m -> m)
    .forEach(m -> System.out.println(m.group()));

Recommended Posts

Un moyen simple de créer une implémentation de java.util.stream.Stream
Un moyen simple de créer des balises personnalisées JSP
Un moyen facile de créer votre propre logo d'application (facile avec votre smartphone)
Manipulez les pixels pour créer une image d'un ensemble de Mandelbrot
Bibliothèque de traitement facile à créer
Implémentation facile de la navigation de fichiers Android
[Rails] Un moyen simple de vérifier les colonnes
Un moyen simple de créer une classe de mappage lors de l'utilisation de l'API
Un moyen simple de définir les icônes des applications iOS
Comment brouiller l'image (super facile)
Implémentation Java pour créer et résoudre des labyrinthes
Convertir un tableau de chaînes en nombres
[Apache Camel] Sortie facile du débit dans un journal
Résumé de la création de balises JSF personnalisées
[Rails] Mise en œuvre de "notifier la notification d'une manière ou d'une autre"
Un moyen très simple d'utiliser enum avec JSP
Rails6.0 ~ Comment créer un environnement de développement respectueux de l'environnement
Comment créer un certificat OLEORE (certificat SSL, auto-certificat)