Sieve of Eratosthenes using Java 8 streams
Implementation

You can invert the values for prime and not prime to avoid the initial rangeClosed(0, _n).forEach(x -&gt; prime[x] = true). The innermost loop can start at x*x instead of x*2:

// (1)
public static List&lt;Integer&gt; sieveOfEratosthenes(int n) {
    boolean[] notPrime = new boolean[n + 1];

    IntStream.rangeClosed(2, (int) Math.sqrt(n))
            .filter(x -&gt; !notPrime[x])
            .forEach(x -&gt; {
                IntStream.iterate(x * x, m -&gt; m &lt;= n, m -&gt; m + x)
                        .forEach(y -&gt; notPrime[y] = true);
            });

    List&lt;Integer&gt; list = new ArrayList&lt;&gt;();
    IntStream.rangeClosed(2, n)
            .filter(x -&gt; !notPrime[x])
            .forEach(x -&gt; list.add(x));
    return list;
}


This implementation still feels like a literal translation of the for-loop approach. Streams offer options to improve readability, i.e. the inner loop can be flattened:  

// (2)
public static List&lt;Integer&gt; sieveOfEratosthenes(int n) {
    boolean[] notPrime = new boolean[n + 1];

    rangeClosed(2, (int) Math.sqrt(n))
            .filter(x -&gt; !notPrime[x])
            .flatMap(x -&gt; iterate(x * x, m -&gt; m &lt;= n, m -&gt; m + x))
            .forEach(x -&gt; notPrime[x] = true);

    return rangeClosed(2, n)
            .filter(x -&gt; !notPrime[x])
            .boxed().collect(toList());
}


Stream vs Loop

The main problem I see with a stream based approach is (besides the overhead of the streams), that it is more difficult to optimize compared to a loop approach as the abstraction level is higher. For example converting the implementation to a parallel approach is in my opinion way more complicated with a stream approach.

Algorithm improvements (not directly related to the question)

You can use a BitSet (or directly a long/int/byte array) to ensure that each entry in the sieve consumes only one bit (instead of currently (likely) 8). You are storing all values from 2 to n in the sieve, you can save memory by skipping multiples of 2 (and 3, 5, ...) at the cost of some additional calculations to convert between sieve position and value.

For larger values of n it might be advantageous to divide the sieving process in smaller steps and use a small array instead of a large array for all values and sieving the complete range at once.

The sieving process can be converted to a parallel implementation with nearly linear speedup as two or more values can be sieved simultaneously (sieving process of each value is independent from other values).

Approx. performance for n=100_000_000, included my implementation (which utilizes most of the improvements mentioned above) as reference value:

// 1 Thread
Initial            3406676978ns
Version (1)        2487619662ns
Version (2)        2459434320ns
For loop           2158261344ns
Nevay to List      1436579484ns
Nevay to Sieve     1040829243ns
// 8 Threads
Nevay to List       682085628ns
Nevay to Sieve      172952467ns