title: Java 8: performance of Streams vs Collections
body: <p>I'm new to Java 8. I still don't know the API in depth, but I've made a small informal benchmark to compare the performance of the new Streams API vs the good old Collections. </p>
  
  <p>The test consists in filtering a list of <code>Integer</code>, and for each even number, calculate the square root and storing it in a result <code>List</code> of <code>Double</code>.</p>
  
  <p>Here is the code:</p>
  
  <pre><code>    public static void main(String[] args) {
          //Calculating square root of even numbers from 1 to N       
          int min = 1;
          int max = 1000000;
  
          List&lt;Integer&gt; sourceList = new ArrayList&lt;&gt;();
          for (int i = min; i &lt; max; i++) {
              sourceList.add(i);
          }
  
          List&lt;Double&gt; result = new LinkedList&lt;&gt;();
  
  
          //Collections approach
          long t0 = System.nanoTime();
          long elapsed = 0;
          for (Integer i : sourceList) {
              if(i % 2 == 0){
                  result.add(Math.sqrt(i));
              }
          }
          elapsed = System.nanoTime() - t0;       
          System.out.printf("Collections: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
  
  
          //Stream approach
          Stream&lt;Integer&gt; stream = sourceList.stream();       
          t0 = System.nanoTime();
          result = stream.filter(i -&gt; i%2 == 0).map(i -&gt; Math.sqrt(i)).collect(Collectors.toList());
          elapsed = System.nanoTime() - t0;       
          System.out.printf("Streams: Elapsed time:\t\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
  
  
          //Parallel stream approach
          stream = sourceList.stream().parallel();        
          t0 = System.nanoTime();
          result = stream.filter(i -&gt; i%2 == 0).map(i -&gt; Math.sqrt(i)).collect(Collectors.toList());
          elapsed = System.nanoTime() - t0;       
          System.out.printf("Parallel streams: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));      
      }.
  </code></pre>
  
  <p>And here are the results for a dual core machine:</p>
  
  <pre><code>    Collections: Elapsed time:        94338247 ns   (0,094338 seconds)
      Streams: Elapsed time:           201112924 ns   (0,201113 seconds)
      Parallel streams: Elapsed time:  357243629 ns   (0,357244 seconds)
  </code></pre>
  
  <p>For this particular test, streams are about twice as slow as collections, and parallelism doesn't help (or either I'm using it the wrong way?).</p>
  
  <p>Questions:</p>
  
  <ul>
  <li>Is this test fair? Have I made any mistake? </li>
  <li>Are streams slower than collections? Has anyone made a good formal benchmark on this?</li>
  <li>Which approach should I strive for?</li>
  </ul>
  
  <hr>
  
  <p><strong>Updated results.</strong></p>
  
  <p>I ran the test 1k times after JVM warmup (1k iterations) as advised by @pveentjer:</p>
  
  <pre><code>    Collections: Average time:      206884437,000000 ns     (0,206884 seconds)
      Streams: Average time:           98366725,000000 ns     (0,098367 seconds)
      Parallel streams: Average time: 167703705,000000 ns     (0,167704 seconds)
  </code></pre>
  
  <p>In this case streams are more performant. I wonder what would be observed in an app where the filtering function is only called once or twice during runtime.</p>