Wie erstelle ich einen Stream von regex-matches?
Ich versuche zu analysieren standard-input und extrahieren Sie alle Strings, die übereinstimmungen mit einem bestimmten Muster, zählen Sie die Anzahl der vorkommen jedes Spiel, und drucken Sie die Ergebnisse alphabetisch. Dieses problem scheint, wie ein gutes match für die Streams-API, aber ich kann nicht finden, einen prägnanten Weg, um erstellen Sie einen stream der Spiele von einem Matcher.
Ich arbeitete um dieses problem durch die Implementierung eines iterator über die Spiele und wickeln Sie es in ein Stream, aber das Ergebnis ist nicht sehr gut lesbar ist. Wie kann ich einen stream erstellen, der der regex entspricht, ohne die Einführung zusätzlicher Klassen?
public class PatternCounter
{
static private class MatcherIterator implements Iterator<String> {
private final Matcher matcher;
public MatcherIterator(Matcher matcher) {
this.matcher = matcher;
}
public boolean hasNext() {
return matcher.find();
}
public String next() {
return matcher.group(0);
}
}
static public void main(String[] args) throws Throwable {
Pattern pattern = Pattern.compile("[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)");
new TreeMap<String, Long>(new BufferedReader(new InputStreamReader(System.in))
.lines().map(line -> {
Matcher matcher = pattern.matcher(line);
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(new MatcherIterator(matcher), Spliterator.ORDERED), false);
}).reduce(Stream.empty(), Stream::concat).collect(groupingBy(o -> o, counting()))
).forEach((k, v) -> {
System.out.printf("%s\t%s\n",k,v);
});
}
}
- in Java 9, gibt es eine Methode Matcher.Ergebnisse. siehe download.java.net/jdk9/docs/api/java/util/regex/...
- sieht aus wie der Java-9-URI geändert hat
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, in Java 8, es ist
- Muster.splitAsStream
, die einen stream von Elementen aufgeteilt Trennzeichen Muster, aber leider keine Unterstützung-Methode für immer ein Strom von entspricht.Wenn Sie gehen, um die Implementierung einer solchen
Stream
empfehle ich die UmsetzungSpliterator
direkt, sondern Implementierung und die Verpackung einesIterator
. Sie können mehr vertraut mitIterator
aber die Implementierung einer einfachenSpliterator
ist straight-forward:Können Sie prüfen, überschreiben
forEachRemaining
mit einer straight-forward-Schleife, obwohl.Wenn ich verstehe Ihren Versuch, korrekt sollte die Lösung Aussehen:
Java 9 stellt eine Methode
Stream<MatchResult> Ergebnisse()
direkt auf dieMatcher
. Aber für die Suche nach übereinstimmungen innerhalb eines stream, es gibt eine bequemere MethodeScanner
. Mit, dass, die Umsetzung vereinfachtDiese Antwort mit einer "zurück" -port des
Scanner.findAll
verwendet werden kann, die mit Java 8.NONNULL
ist möglichIMMUTABLE
angegeben werden kann, wenn die Quelle einString
und Sie haben die volle Kontrolle über dieMatcher
alsMatcher
's Eigenschaften dürfen nicht geändert werden, wie gut (vor allem der Quelle), aber die Angabe dieser flags ist nicht so wichtig wie derzeit, niemand nutzt diese Flaggen...Geht aus von Holger ' s Lösung, die wir unterstützen können beliebige
Matcher
Operationen (wie die nth-Gruppe), indem der Benutzer eineFunction<Matcher, String>
Betrieb. Wir können auch ausblenden, dieSpliterator
als eine Implementierung detail, so dass Anrufer nur die Arbeit mit denStream
direkt. Als Faustregel gilt:StreamSupport
verwendet werden soll, indem Sie den Bibliotheks-code, anstatt die Benutzer.Dann können Sie es gerne so:
Oder für Ihre spezielle Aufgabe ("borrowing wieder von Holger):
Stream<MatchResult>
denke ich. Sie nicht zulassen möchten, dass Funktionen, die mutieren, dieMatch
, und dann ordnen Sie es zu einemStream<String>
zu befriedigen OP mitStream::map
MatchResult
.Wenn Sie möchten, verwenden Sie eine
Scanner
zusammen mit regulären Ausdrücken mit derfindWithinHorizon
Methode könnte man auch konvertieren einen regulären Ausdruck in einen stream von strings.Hier verwenden wir einen Strom-generator, die sehr bequem ist zu verwenden bei einer konventionellen
while
Schleife.Hier ist ein Beispiel: