2017-09-18 2 views
2

Da gepufferter Leser ist viel schneller als Scanner-Klasse im Falle der Eingabe von Werten vom Benutzer, aber wie in den meisten der Algorithmus Wettbewerbe beobachtet oder im Falle von Interviews gibt es oft mehrere ganze Zahlen auf einer einzigen Eingabezeile. Daher wird es einfacher Scanner Klasse zu verwenden -Ist es optimal, BufferedReader anstelle der Scanner-Klasse für mehrere Ganzzahlen in einer einzigen Zeile in Java zu verwenden?

Scanner in=new Scanner(System.in); 
    int a=in.nextInt(); 
    int b=in.nextInt(); 

Bei Buffered Reader, werden Sie zum ersten Eingang haben eine Linie (da es keine Möglichkeit, readInt ist) und dann die Zeile parsen nach Anzahl der ganzen Zahlen auf sie -

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    int a,b; 
    String line = br.readLine(); 
    String[] strs = line.trim().split("\\s+"); 
    a=Integer.parseInt(strs[0]); 
    b=Integer.parseInt(strs[1]); 

Obwohl die Eingabe in diesem Fall schneller kann, wird die Analyse viel Zeit in Anspruch nimmt die erhaltene Zeichenkette in indiviual ganzen Zahlen zu teilen? In so einem Fall, welcher der oben genannten ist optimal oder schneller?

Vielen Dank.

+1

Wenn Sie es schaffen, den Unterschied tatsächlich wahrzunehmen, dann haben Sie ein ganz anderes Problem. – Fildor

+0

Der schnellste Weg ist wahrscheinlich, einen Block von Bytes in ein Array zu lesen, über jedes Byte zu iterieren und Zeichenfolgen manuell in ganzzahlige Werte umzuwandeln. Dies vermeidet die Zuweisung von String-Objekten und den Aufruf von split() oder die Verwendung von Regexes. – Nayuki

+0

Ich bin neu im Stack-Overflow, vielleicht hätte ich auf weitere Antworten warten sollen. Ihre Antwort funktionierte gut, aber Danke! – user8321763

Antwort

3

Sehr falsche Ansatz: Sie sprechen über Benutzereingabe. Es ist absolut egal wie Sie verarbeiten etwas, das auf menschlichen Zeitskala zur Verfügung gestellt wird.

Ein Mensch arbeitet auf "Sekunden", in einigen Szenarien auf "Millisekunden".

Während das Delta zwischen einem Scanner und einem BufferedReader in Bezug auf Leistung ist wahrscheinlich im Bereich von Mikro Sekunden, vielleicht sogar nano Sekunden.

Und selbst wenn wir nicht über eine menschliche Person Eingabe Inhalt auf der Konsole (aber mit Rohrleitungen, wie cat somefile | java Whatever) zu sprechen - Sie haben noch IO in großem Umfang geschehen. Ihre Anwendung wird 99,99% ihrer Zeit damit verbringen, auf IO zu warten. Wie die eingehenden Strings am Ende verarbeitet werden, spielt dabei keine Rolle.

Mit anderen Worten: Sie besser Ihre Zeit damit verbracht sauber Code zu schreiben, dass der Job in einem geraden Weg nach vorn getan wird, das einfach zu seinen menschlichen Lesern zu verstehen. Und dann lass das JIT seine Magie machen.

Da die Frage speziell auf die Verarbeitung "dateibasierter" Eingabe gerichtet ist, gehen Sie Profil selbst. Was würde ich hier tun:

  • eine Abstraktionsschicht erstellen, die mich zu leicht Wechsel zwischen verschiedenen Implementierungen
  • ermöglicht
  • dann würde ich zu Benchmark verschiedene Lösungen starten (lesen Sie sorgfältig this für eine solche Vorbereitung Aktivität)

Sie sehen, am Ende beiden Teile des Codes tun sehr ähnlich Dinge.Ein Scanner arbeitet noch an etwas, und Sie müssten für eine gewisse Zeit in den entsprechenden Quellcode eintauchen, um mögliche Unterschiede zwischen Scanner-Parsing und BufferedReader lesen + manuelles Parsing zu verstehen.

+0

Die Frage schlug vor, dass die Eingabe aus einer Textdatei stammen könnte, wie ein Testfall in einem Programmierwettbewerb. – Nayuki

+0

@Nayuki Ich habe meine Antwort überarbeitet, um auch diesen Teil anzusprechen. – GhostCat

+1

Ja, ich verstehe vollkommen, was du sagen willst. Mein Problem ist jedoch nicht gegen menschliche Eingaben, sondern die bereits entwickelten Code-Compiler und Testfälle. In meinem Beispiel habe ich zwei Ganzzahlen verwendet, aber die von einigen Code-Testern verwendeten Testfälle können bis zu 10^5 Eingänge umfassen. In solchen Szenarien beträgt die zulässige Ausführungszeit ungefähr 1 Sekunde oder sogar weniger. Also, wäre es nicht wichtig (zeitweise), einen String zu teilen, der ungefähr 10^5 ganze Zahlen enthält, um ihn in ein String-Array von 10^5 Größe aufzuteilen und dann jeden Wert in Integer zu parsen. – user8321763

3

Dies ist einer der Fälle, in denen Code-Klarheit wichtiger ist als die Geschwindigkeit.

Es ist leicht zu sehen, dass der Code mit Scanner geht auf den Punkt, was los ist, und liest sehr natürlich.

Auf der anderen Seite, der Code mit BufferedReader führt einige zusätzliche Aufgaben vor tun, was es tun muss (Lesen von zwei ganzen Zahlen von der Eingabe), damit ein Leser Ihres Codes ein paar Sekunden verbringen, um zu sehen, was vor sich geht .

Natürlich, einige Fehlerbehandlung Code fehlt beiden Implementierungen. Zum Beispiel muss die zweite Implementierung überprüfen, dass split genau zwei Elemente zurückgegeben hat. Wenn die erste Implementierung alle Fehlerüberprüfungen auslässt, würde der Aufrufer eine Nachricht erhalten, dass es keine Ganzzahl in der Eingabe gibt. Die zweite Implementierung würde eine Index-außerhalb-Bereich-Ausnahme erhalten, die zusätzliche Forschung erfordern würde, um zu sehen, was vor sich geht.

Soweit das Parsing geht, muss es in beiden Fällen passieren, so dass Sie am Ende ungefähr die gleiche Anzahl von CPU-Zyklen ausgeben würden, um es zu verarbeiten.

Verwandte Themen