2015-05-13 24 views
15
FileWriter writer = new FileWriter(output_file); 
    int i = 0; 

    try (Stream<String> lines = Files.lines(Paths.get(input_file))) { 
     lines.forEach(line -> { 
      try { 
       writer.write(i + " # " + line + System.lineSeparator()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
        ); 
     writer.close(); 
    } 

Ich muss die Zeile mit der Zeilennummer schreiben, also habe ich versucht, einen Zähler in .forEach() hinzuzufügen, aber ich kann es nicht zum Laufen bringen. Ich weiß nur nicht, wo ich das i ++ setzen soll; In den Code half das zufällige Herumschrauben bisher nicht.Wie fügt man einen Zähler in einen Stream ein <String> .forEach()?

+0

Deklarieren Sie ein int außerhalb der Schleife, setzen Sie es auf 0, und erhöhen Sie es bei jeder Iteration. – Stultuske

+0

@Stultuske Funktioniert das? Hast du es versucht? Beachten Sie, dass es hier keine Schleife gibt, aber es gibt ein Lambda. – immibis

+0

Das ist die Frage, ich habe ein int i = 0; außerhalb des Lambda, aber ich kann es nicht in jedem for.Each() -Zyklus erhöhen. Stultuske las weder den Code noch die Frage, nur das Thema. – Vega

Antwort

9

Dies ist ein gutes Beispiel, wo Sie lieber eine gute altmodische For-Schleife verwenden sollten. Während Files.lines() speziell einen sequenziellen Stream gibt, können Streams außerhalb der Reihenfolge erzeugt und verarbeitet werden, so dass das Einfügen von Zählern und das Verweisen auf deren Reihenfolge eine ziemlich schlechte Angewohnheit ist, hineinzukommen. Wenn Sie es immer noch tun möchten, denken Sie daran, dass Sie überall, wo Sie ein Lambda verwenden können, immer noch eine vollständige anonyme Klasse verwenden können. Anonyme Klassen sind normale Klassen und können als solche einen Status haben.

Also in Ihrem Beispiel könnten Sie tun, wie folgt:

FileWriter writer = new FileWriter(output_file); 

try (Stream<String> lines = Files.lines(Paths.get(input_file))) { 
    lines.forEach(new Consumer<String>() { 
     int i = 0; 
     void accept(String line) { 
      try { 
       writer.write((i++) + " # " + line + System.lineSeparator()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
    writer.close(); 
} 
37

Sie können einen AtomicInteger als einen veränderbaren final Zähler verwenden.

+0

@ AndreaTaroni86 - Warum? – OldCurmudgeon

4

Wie in Java doc erklärte:

Jeder lokale Variable, formale Parameter oder verwendet Ausnahme Parameter aber nicht in einem Lambda erklärt Ausdruck muss entweder als final deklariert werden oder ist effektiv final (§4.12.4), oder es tritt ein Kompilierungsfehler auf, wenn die Verwendung versucht wird.

Es bedeutet, dass Ihre Variable endgültig oder effektiv final sein muss. Sie möchten einen Zähler in forEach hinzufügen und dafür können Sie eine AtomicInteger wie von OldCurumudgeon vorgeschlagen, die IMO eine bevorzugte Vorgehensweise ist.

Ich glaube, Sie können auch ein Array mit nur einem Wert 0 verwenden, die Sie als Zähler verwenden können. Überprüfen Sie, ob das folgende Beispiel für Sie funktioniert: