Der reguläre Ausdruck von Java bietet einen Leistungsvorteil?

8

In Java, wenn wir versuchen, einen Mustervergleich mit einem regulären Ausdruck durchzuführen. z.B. Nehmen Sie eine Eingabezeichenfolge und verwenden Sie regulären Ausdruck, um herauszufinden, ob es numerisch ist. Wenn nicht, eine Ausnahme auslösen. In diesem Fall verstehe ich, dass die Verwendung von Regex den Code weniger ausführlich macht, als wenn wir jedes Zeichen des Strings nehmen würden, prüfen, ob es sich um eine Zahl handelt und wenn keine Ausnahme ausgelöst wird.

Aber ich ging davon aus, dass Regex auch den Prozess effizienter macht. Ist das wahr? Ich kann in diesem Punkt keine Beweise finden. Wie macht Regex das Spiel hinter den Kulissen? WENN es nicht auch über die Zeichenkette iteriert und jedes Zeichen einzeln überprüft?

    
Victor 09.08.2012, 01:07
quelle

8 Antworten

4

Nur zum Spaß habe ich diesen Mikro-Benchmark laufen lassen. Die Ergebnisse des letzten Laufs (d. H. JVM-Aufwärmphase / JIT) sind unten angegeben (die Ergebnisse sind von einem Lauf zum anderen sowieso ziemlich konsistent):

%Vor%

Mit anderen Worten, chars ist sehr effizient, Integer.parseInt ist genauso effizient wie char, wenn die Zeichenfolge eine Zahl ist, aber schrecklich langsam, wenn die Zeichenfolge keine Zahl ist. Regex ist dazwischen.

Fazit

Wenn Sie eine Zeichenfolge in eine Zahl analysieren und erwarten, dass die Zeichenfolge im Allgemeinen eine Zahl ist, ist die Verwendung von Integer.parseInt die beste Lösung (effizient und lesbar). Die Strafe, die du erhältst, wenn die Zeichenfolge keine Zahl ist, sollte niedrig sein, wenn sie nicht zu häufig ist.

ps: meine Regex ist vielleicht nicht optimal, fühlen Sie sich frei zu kommentieren.

%Vor%     
assylias 09.08.2012, 01:25
quelle
3

Ich habe noch keine technische Antwort, aber ich könnte etwas Code schreiben und sehen. Ich glaube nicht, dass reguläre Ausdrücke der Weg wären, eine Zeichenkette in eine Zahl umzuwandeln. In vielen Fällen können sie effizienter sein, aber wenn es schlecht geschrieben ist, wird es langsam sein.

Darf ich fragen, warum benutzen Sie nicht einfach: %Code%? Das wird eine NumberFormatException auslösen. Sollte in der Lage sein, damit umzugehen, und es lässt die Erkennung einer Nummer bis Core-Java.

    
Teh Hippo 09.08.2012 01:18
quelle
1

Über Regex hinter den Kulissen ...

Ein endlicher Automat (FSM) entspricht einem regulären Ausdruck. FSM ist eine Maschine, die eine Sprache (in Ihrem Fall Zahlen) erkennen kann. FSM hat ein Alphabet, Zustände, einen Anfangszustand, N-Endzustände und Übergangsfunktionen von einem Zustand zu einem anderen. Die Zeichenfolge muss im Alphabet enthalten sein (z. B. ASCII). Die FSM beginnt im Ausgangszustand. Wenn Sie eine Zeichenkette eingeben, wird char von char in Abhängigkeit von einer Funktion von Zustand zu Zustand verschoben (state, char) = & gt; Zustand. Wenn es einen Endzustand erreicht, wissen Sie, ob Sie eine Zahl numerisch eingeben oder nicht.

Weitere Informationen finden Sie unter FSM und in Automatenbasierte_programmierung

    
user1154664 09.08.2012 01:43
quelle
1

Ich sehe nicht, wie es einfacher oder einfacher werden könnte zu lesen als:

Integer.parseInt()

oder

Double.parseDouble()

Sie tun genau das, was Sie beschreiben, einschließlich einer Exception für ungültige Eingabe.

Was die Leistung betrifft: Ich würde erwarten, dass eine Regex weniger effizient ist als die oben genannten.

    
jahroy 09.08.2012 01:45
quelle
1

Nur meine 5 Cent :) Im Allgemeinen ist die Regular Expressions-Sprache nicht dazu gedacht, ganze Zahlen oder Strings zu parsen. Es ist ein ziemlich mächtiges Werkzeug, das es erlaubt, jeden 'regulären Ausdruck' zu erkennen. Es erinnert mich an meine Uni-Zeit (Remember Automatentheorie Kurs? :), aber hier ist der Link , der beschreibt, was die reguläre Sprache ist Wirklich ist

Jetzt Da es FSMs erstellt, bringt es etwas Overhead mit sich, also ist vielleicht für Integer.parseInt reguläre Ausdrucksmodule kein guter Ersatz, außerdem hat Java die spezifischere API eingeführt. Reguläre Ausdrücke haben jedoch einen Vorteil, wenn Sie mit komplexeren Ausdrücken arbeiten und wenn wir viele davon haben.

Der reguläre Ausdruck muss mit Bedacht verwendet werden. Das Muster muss immer kompiliert werden (andernfalls kann es nicht effizient wiederverwendet werden, da jedes Mal, wenn das Muster zusammengesetzt wird, die Leistung beeinträchtigt wird)

Ich würde vorschlagen, den Test für komplexere Eingaben durchzuführen und zu sehen, was passiert.

    
Mark Bramnik 09.08.2012 05:04
quelle
0

Nun, es ist schwer zu sagen, aber im Allgemeinen sind reguläre Ausdrücke im Vergleich zur expliziten Zeichenprüfung wahrscheinlich weniger effizient. RE ist ein Endzustandsautomat, daher gibt es einen gewissen Mehraufwand beim Erstellen und Beibehalten von Automaten. In meiner Praxis ist expliziter Code immer schneller (und damit effizienter) als reguläre Ausdrücke.

Aber hier ist das Dilemma. Reguläre Ausdrücke sind von der Zeit bis zur Auslieferung fast immer effizienter und bei richtiger Verwendung lesbarer . Und hier ist ein weiteres Dilemma. Ich sehe selten korrekte Verwendung von regulären Ausdrücken ...

In Ihrem Szenario schlage ich vor, die Guava-Bibliothek zu verwenden:

%Vor%     
Denis Bazhenov 09.08.2012 01:20
quelle
0

Am Ende iteriert es tatsächlich über die Zeichenfolge und überprüft jedes Zeichen, das versucht, Übereinstimmung für das bereitgestellte Muster zu finden. Darüber hinaus verwendet es Backtracking (wenn es viele Möglichkeiten gibt, die passen könnten, wird Engine sie alle ausprobieren), was in einigen ungewöhnlichen Fällen zu einer sehr schlechten Performance führen kann (nicht wahrscheinlich, dass Sie darauf stoßen, aber theoretisch möglich). Im schlimmsten Fall ist die Leistung der Java-Engine für reguläre Ausdrücke O (2 N ), wobei N die Länge der Eingabezeichenfolge ist.

Es gibt Algorithmen für einen viel schnelleren Mustervergleich, der eine O (N) -Leistung liefert, aber mit weniger Features im Vergleich zu regulären Java-Ausdrücken.

Hier ist ein Artikel, der diese Frage ausführlich diskutiert.

In den meisten Fällen ist die Engine für reguläre Ausdrücke jedoch nicht der Leistungsengpass in Ihrer Anwendung. Es ist schnell genug, also mach dir normalerweise keine Sorgen, es sei denn, dein Profiler weist darauf hin. Und es bietet eine deklarative Beschreibung des Algorithmus, die sehr nützlich ist, weil fast immer iterative Algorithmus-Implementierung wird viel ausführlicher und viel weniger lesbar.

    
vbezhenar 09.08.2012 01:24
quelle
0

Um Ihre Frage spezifisch zu beantworten:

Warum wenden Sie eine Regex-Musterübereinstimmung nicht auf einen komplexen Text an und versuchen dann, denselben übereinstimmenden Code selbst zu schreiben.

Sehen Sie, was schneller ist.

Antwort: Die Regex.

    
deleted_user 09.08.2012 01:39
quelle

Tags und Links