2015-05-13 30 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(); 
    } 

Satır numarasını satır ile yazmalıyım, bu nedenle .forEach() öğesine bir sayaç eklemeye çalıştım, ancak çalışamayacağım. Sadece i + 'yi nereye koyacağımı bilmiyorum; Kod içine, rastgele vidalama, şu ana kadar yardımcı olmadı.Akışa <String> .forEach() nasıl eklenir?

+0

Döngünün dışından bir aralık bildirin, 0 olarak ayarlayın ve her yinelemeyi artırın. – Stultuske

+0

@Stultuske Bu işe yarıyor mu? Bunu denediniz mi? Burada herhangi bir döngü olmadığını unutmayın, ama bir lambda var. – immibis

+0

Bu soru bir int i = 0; lambda dışında, ama her for.Each() döngüsünde artırmak için alamıyorum. Stultuske ne kodu ne de soruyu okuyor, sadece konu. – Vega

cevap

9

Bu, güzel bir eski moda döngüsünü kullanmanız gereken yerlere iyi bir örnektir. Files.lines() spesifik olarak bir sıralı akış sağlarken, akışlar sıraya göre üretilip işlenebilir, böylece sayaçların yerleştirilmesi ve siparişlerine güvenilmesi, içine girmek için oldukça kötü bir alışkanlıktır. Eğer hala bunu gerçekten yapmak istiyorsanız, bir lambda kullanabileceğiniz her yerde, anonim bir sınıfı hala kullanabileceğinizi unutmayın. Anonim sınıflar normal sınıflardır ve böyle bir duruma sahip olabilirler.

Yani örnekte böyle yapabilirdi:

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

AtomicInteger, dönüştürülebilir bir final sayacı olarak kullanabilirsiniz.

public void test() throws IOException { 
    // Make sure the writer closes. 
    try (FileWriter writer = new FileWriter("OutFile.txt")) { 
     // Use AtomicInteger as a mutable line count. 
     final AtomicInteger count = new AtomicInteger(); 
     // Make sure the stream closes. 
     try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) { 
      lines.forEach(line -> { 
         try { 
          // Annotate with line number. 
          writer.write(count.incrementAndGet() + " # " + line + System.lineSeparator()); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
        } 
      ); 
     } 
    } 
} 
+0

@ AndreaTaroni86 - Neden? – OldCurmudgeon

4

Java doc belirtildiği gibi: Kullanılan

Herhangi yerel değişken, biçimsel parametre veya istisna parametresi ama bir lambda bildirilmedi İfade, son olarak bildirilmelidir veya etkin bir şekilde nihai olmalıdır (§4.12.4) veya kullanımının denendiği bir derleme zamanı hatası oluşur.

Değişkeninizin son veya etkili olması gerektiği anlamına gelir. forEach numarasına bir sayaç eklemek istiyorsunuz ve bunun için IMO'nun tercih edilen bir yaklaşım olan OldCurumudgeon tarafından önerildiği gibi bir AtomicInteger kullanabilirsiniz.

Ayrıca, sayaç olarak kullanabileceğiniz yalnızca bir 0 değerine sahip bir dizi de kullanabilirsiniz. Aşağıdaki örnek sizin için çalışıp çalışmadığını kontrol edip bana bildirin:

public void test() throws IOException { 
    FileWriter writer = new FileWriter("OutFile.txt"); 
    final int[] count = {0}; 

    try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) { 
     lines.forEach(line -> { 
      try { 
       count[0]++; 
       writer.write(count[0] + " # " + line + System.lineSeparator()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     ); 
     writer.close(); 
    } 
}