-
Enhancement
-
Resolution: Unresolved
-
P3
-
None
-
None
These statements should work:
A: for (String x : Stream.of("foo", "bar")) System.out.println(x);
B: for (int x : IntStream.range(0,2)) System.out.println(x);
Available workarounds seem to be insufficient:
1. The user can call Stream.forEach instead of writing a for-loop, but in that case control transfer statements (break/continue/return) are not available, for short-circuit logic. In some cases this is a deal-killer.
2. The user can call Stream.toArray and iterate over the result. But this forces the stream to enumerate all values up front, defeating (again) some algorithms that would use short-circuit logic. It also pushes the iteration space through a buffer, making optimization difficult.
3. The user can follow the stream by "::iterator" to make a method reference which can be then converted to an Iterable using a cast. (See below.) But adding decorations before and after the stream expressions is difficult to discover (either by hand or in an IDE) when writing code, and difficult to read once it is written. Also, the idiom forces primitives to be boxed.
A: for (String x : (Iterable<String>) Stream.of("foo", "bar")::iterator) ...
B: for (int x : (Iterable<Integer>) IntStream.range(0,2)::iterator) ...
To properly support use case A, Stream should implement Iterable. This is a library-only change.
In the use case B, either IntStream should implement Iterable<int>, or else the JLS definition of for-each (14.14.2) should define primitive versions of Iterable by analogy with PrimitiveIterator.OfInt, etc.
It would seem that the graceful thing to do, for primitives, is to wait for any-generics (Iterable<int>).
But before any-generics it would be useful to make stream types implement Iterable. Then the primitive version could be made to work (well enough in many cases) using the "boxed" stream transform:
A: for (String x : Stream.of("foo", "bar")) ...
B: for (int x : IntStream.range(0,2).boxed()) ...
A: for (String x : Stream.of("foo", "bar")) System.out.println(x);
B: for (int x : IntStream.range(0,2)) System.out.println(x);
Available workarounds seem to be insufficient:
1. The user can call Stream.forEach instead of writing a for-loop, but in that case control transfer statements (break/continue/return) are not available, for short-circuit logic. In some cases this is a deal-killer.
2. The user can call Stream.toArray and iterate over the result. But this forces the stream to enumerate all values up front, defeating (again) some algorithms that would use short-circuit logic. It also pushes the iteration space through a buffer, making optimization difficult.
3. The user can follow the stream by "::iterator" to make a method reference which can be then converted to an Iterable using a cast. (See below.) But adding decorations before and after the stream expressions is difficult to discover (either by hand or in an IDE) when writing code, and difficult to read once it is written. Also, the idiom forces primitives to be boxed.
A: for (String x : (Iterable<String>) Stream.of("foo", "bar")::iterator) ...
B: for (int x : (Iterable<Integer>) IntStream.range(0,2)::iterator) ...
To properly support use case A, Stream should implement Iterable. This is a library-only change.
In the use case B, either IntStream should implement Iterable<int>, or else the JLS definition of for-each (14.14.2) should define primitive versions of Iterable by analogy with PrimitiveIterator.OfInt, etc.
It would seem that the graceful thing to do, for primitives, is to wait for any-generics (Iterable<int>).
But before any-generics it would be useful to make stream types implement Iterable. Then the primitive version could be made to work (well enough in many cases) using the "boxed" stream transform:
A: for (String x : Stream.of("foo", "bar")) ...
B: for (int x : IntStream.range(0,2).boxed()) ...
- relates to
-
JDK-8186220 clarify semantics of Iterable
-
- Open
-
-
JDK-8181054 add Iterator.stream() default method
-
- Open
-