Here is the answer to turn to the OP from another aspect. First of all, let's see how to quickly / slowly iterate over a list / collection. Here is the test result on my machine using the performance test below:
When: line list length = 100, stream number = 1, cycles = 1000, unit = milliseconds
OP: 0.013
Accepted Answer: 0.020
In counter function: 0.010
When: row list length = 1000_000, stream number = 1, loops = 100, unit = milliseconds
OP: 99.387
Accepted Answer: 89.848
Counter Function: 59.183
Conclusion The percentage of performance improvement is rather small or even slower (if the length of the list of lines is small). This is usually a mistake to reduce the iteration of the list / collection, which is loaded into memory by a more complex collector. You wonโt get big performance improvements. we should look elsewhere if there is a performance problem.
Here is my performance test code with the Profiler tool: (I wonโt discuss how to perform a performance test here. If you doubt the test results, you can do it again using any tool you believe in)
@Test public void test_46539786() { final int strsLength = 1000_000; final int threadNum = 1; final int loops = 100; final int rounds = 3; final List<String> strs = IntStream.range(0, strsLength).mapToObj(i -> i % 2 == 0 ? i + " of " + i : i + " for " + i).toList(); Profiler.run(threadNum, loops, rounds, "OP", () -> { List<Integer> wordsInStr = strs.stream().filter(t -> t.contains("of")).map(t -> t.split(" ").length).collect(Collectors.toList()); List<String> linePortionAfterFor = strs.stream().filter(t -> t.contains("for")).map(t -> t.substring(t.indexOf("for"))) .collect(Collectors.toList()); assertTrue(wordsInStr.size() == linePortionAfterFor.size()); }).printResult(); Profiler.run(threadNum, loops, rounds, "Accepted answer", () -> { Splitter collect = strs.stream().collect(Collector.of(Splitter::new, Splitter::accept, Splitter::merge)); assertTrue(collect.counts.size() == collect.words.size()); }).printResult(); final Function<String, Integer> counter = s -> { int count = 0; for (int i = 0, len = s.length(); i < len; i++) { if (s.charAt(i) == ' ') { count++; } } return count; }; Profiler.run(threadNum, loops, rounds, "By the counter function", () -> { List<Integer> wordsInStr = strs.stream().filter(t -> t.contains("of")).map(counter).collect(Collectors.toList()); List<String> linePortionAfterFor = strs.stream().filter(t -> t.contains("for")).map(t -> t.substring(t.indexOf("for"))) .collect(Collectors.toList()); assertTrue(wordsInStr.size() == linePortionAfterFor.size()); }).printResult(); }