Получение количества строк при одновременной обработке строк с использованием лямбд

#java #bufferedreader #java-11

#java #bufferedreader #java-11

Вопрос:

Я пытаюсь получить количество строк, которые были обработаны лямбда-символом, перебирающим строки в BufferedReader.

Есть ли способ получить количество без записи 2-й лямбды, чтобы получить только количество строк?

         final BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

        inReader.lines().forEach(line -> {
            
            // do something with the line
         });
 

Могу ли я получить количество также в приведенном выше блоке кода? Я использую Java 11.

Ответ №1:

Если я вас правильно понял, вы хотите посчитать в своем lamba. Конечно, вы можете это сделать. Просто инициализируйте count переменную перед выполнением forEach и увеличьте значение count в вашем лямбда-блоке. Вот так:

 final BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

// fixed the long by this
final AtomicLong counter = new AtomicLong();
inReader.lines().forEach(line -> {
  counter.incrementAndGet();
  // do something with the line
});
// here you can do something with the count variable, like printing it out
System.out.printf("count=%d%n", counter.get());
 

forEach Метод происходит от Iterable . Это определенно не тот способ, который я бы выбрал для обработки reader. Я бы сделал что-то вроде этого:

 try (BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
  Stream<String> lines = inReader.lines();
  
  long i = lines.peek(line -> {
        
        // do something with the line
     }).count();
  
  System.out.printf("count=%d%n", i);
 

}

PS: на самом деле я это не проверял, поэтому поправьте меня, если я допустил ошибку.

Ответ №2:

попробуйте это:

 AtomicLong count = new AtomicLong();
lines.stream().forEach(line -> {
    count.getAndIncrement();
    // do something with line;
});
 

Комментарии:

1. Правильно. Потоки имеют два типа функций: терминальные и не терминальные. Нетерминальные операции возвращают поток, а терминал возвращает что-то еще. forEach является терминалом, и вы не можете вызвать count в результате, потому что это не поток. С другой стороны, peek — это нетерминальная операция, которая выполняет то же самое — применяет потребителя к потоку — но возвращает тот же steam, полученный в качестве входных данных, так что теперь вы можете вызвать count() для результата.