title: Java 8 streams vs iterator performance
body: <p>I'm comparing 2 ways to filter lists, with and without using streams. It turns out that the method without using streams is faster for a list of 10,000 items. I'm interested in understanding why is it so. Can anyone explain the results please?</p>
  
  <pre><code>public static int countLongWordsWithoutUsingStreams(
          final List&lt;String&gt; words, final int longWordMinLength) {
      words.removeIf(word -&gt; word.length() &lt;= longWordMinLength);
  
      return words.size();
  }
  
  public static int countLongWordsUsingStreams(final List&lt;String&gt; words, final int longWordMinLength) {
      return (int) words.stream().filter(w -&gt; w.length() &gt; longWordMinLength).count();
  }
  </code></pre>
  
  <p>Microbenchmark using JMH:</p>
  
  <pre><code>@Benchmark
  @BenchmarkMode(Throughput)
  @OutputTimeUnit(MILLISECONDS)
  public void benchmarkCountLongWordsWithoutUsingStreams() {
      countLongWordsWithoutUsingStreams(nCopies(10000, "IAmALongWord"), 3);
  }
  
  @Benchmark
  @BenchmarkMode(Throughput)
  @OutputTimeUnit(MILLISECONDS)
  public void benchmarkCountLongWordsUsingStreams() {
      countLongWordsUsingStreams(nCopies(10000, "IAmALongWord"), 3);
  }
  
  public static void main(String[] args) throws RunnerException {
      final Options opts = new OptionsBuilder()
          .include(PracticeQuestionsCh8Benchmark.class.getSimpleName())
          .warmupIterations(5).measurementIterations(5).forks(1).build();
  
      new Runner(opts).run();
  }
  </code></pre>
  
  <p>java -jar target/benchmarks.jar -wi 5 -i 5 -f 1
  <p>
  Benchmark<br>                                                                  Mode  Cnt    Score    Error   Units<br>
  PracticeQuestionsCh8Benchmark.benchmarkCountLongWordsUsingStreams         thrpt    5   <strong>10.219</strong> ±  0.408  ops/ms<br>
  PracticeQuestionsCh8Benchmark.benchmarkCountLongWordsWithoutUsingStreams  thrpt    5  <strong>910.785</strong> ± 21.215  ops/ms</p>
  
  <p><strong>Edit:</strong> (as someone deleted the update posted as an answer)</p>
  
  <pre><code>public class PracticeQuestionsCh8Benchmark {
      private static final int NUM_WORDS = 10000;
      private static final int LONG_WORD_MIN_LEN = 10;
  
      private final List&lt;String&gt; words = makeUpWords();
  
      public List&lt;String&gt; makeUpWords() {
          List&lt;String&gt; words = new ArrayList&lt;&gt;();
          final Random random = new Random();
  
          for (int i = 0; i &lt; NUM_WORDS; i++) {
              if (random.nextBoolean()) {
                  /*
                   * Do this to avoid string interning. c.f.
                   * http://en.wikipedia.org/wiki/String_interning
                   */
                  words.add(String.format("%" + LONG_WORD_MIN_LEN + "s", i));
              } else {
                  words.add(String.valueOf(i));
              }
          }
  
          return words;
      }
  
      @Benchmark
      @BenchmarkMode(AverageTime)
      @OutputTimeUnit(MILLISECONDS)
      public int benchmarkCountLongWordsWithoutUsingStreams() {
          return countLongWordsWithoutUsingStreams(words, LONG_WORD_MIN_LEN);
      }
  
      @Benchmark
      @BenchmarkMode(AverageTime)
      @OutputTimeUnit(MILLISECONDS)
      public int benchmarkCountLongWordsUsingStreams() {
          return countLongWordsUsingStreams(words, LONG_WORD_MIN_LEN);
      }
  }
  public static int countLongWordsWithoutUsingStreams(
      final List&lt;String&gt; words, final int longWordMinLength) {
      final Predicate&lt;String&gt; p = s -&gt; s.length() &gt;= longWordMinLength;
  
      int count = 0;
  
      for (String aWord : words) {
          if (p.test(aWord)) {
              ++count;
          }
      }
  
      return count;
  }
  
  public static int countLongWordsUsingStreams(final List&lt;String&gt; words,
      final int longWordMinLength) {
      return (int) words.stream()
      .filter(w -&gt; w.length() &gt;= longWordMinLength).count();
  }
  </code></pre>