Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams

Peter Levart peter.levart at
Thu Mar 7 08:41:14 UTC 2019


I see this is already discussed in the "Alternatives" section of the 
proposal (sorry for not reading this through before asking)...

But I don't quite understand the following part that talks about making 
IterableOnce a supertype of Iterable:

"However, doing so would require weakening the contract of IterableOnce. 
To allow Iterable to be a subtype, the semantics of IterableOnce would 
need to change to allow iteration once and possibly more, instead of the 
currently proposed at-most-once semantics. Having IterableOnce be a 
subtype allows the specification to make a much stronger assertion."

Why would that require "weakening the contract of IterableOnce" ? 
Because if IterableOnce was specified to throw exception on the 2nd and 
subsequent invocations, some instances (those implementing Iterable) 
would not respect that?

I see this as less evil than doing the other way around. How many 
situations will rely on IterableOnce to throw exception vs. how many 
situations will rely on Iterable to allow multiple invocations?

But I agree with assessment that changing language to retrofit foreach 
loop to work with a supertype of Iterable (although it seems a backwards 
compatible change) would be too costly for this feature.

And there are already other similar decisions made in API design of 
Java. For example Collections framework with immutable vs. mutable 
collections. This distinction is not even encoded in type(s). But this 
API was designed from the beginning with that in mind and therefore most 
code consuming collection types documents how it uses the passed-in 
collections (whether it only reads from them or also modifies them). 
Consumers of Iterable(s) did not have that requirement from the 
beginning. If they had, we would not need a special type to mark the 
distinction. The specification of Iterable could simply state that: 
"There are two kinds of Iterable(s) in this world: those that may be 
iterated only once and those that can be iterated multiple times"...

OTOH, having a separate type for only-once iterables would only help 
identify instances of them, but would not help in documenting the 
consumers. Consumers would still have to document this via javadoc. I 
would not recommend consumers to take parameters of type IterableOnce if 
IterableOnce was a subtype of Iterable, because they would unnecessarily 
restrict themselves to consume just the less capable instances.

In addition, introduction of IterableOnce as a subtype of Iterable does 
not help in (re)specifying the Iterable type. There will be two kinds of 
Iterable(s) in the new world regardless of that.

There is a benefit in the runtime though. The code can decide what to do 
with the passed-in Iterable depending on it implementing IterableOnce or 
not. Much like what RandomAccess interface does to List(s). The code can 
decide to dump the iterable into a List and iterate the List multiple 
times if the Iterable implements IterableOnce or do direct multiple 
iteration on the passed-in Iterable if it doesnt.

Regards, Peter

On 3/6/19 4:50 PM, Peter Levart wrote:
> Hi Stuart,
> According to Liskov substitution principle:
>     Subtype Requirement: Let ϕ ( x ) be a property provable about 
> objects x of type T. Then ϕ ( y ) should be true for objects y of type 
> S where S is a subtype of T.
> Let ϕ ( x ) for objects x of type Iterable be: "x.iterator() may be 
> invoked multiple times, each time starting new iteration".
> This clearly holds.
> Does ϕ ( y ) hold for objects y of type IterableOnce? Clearly not.
> In this respect Iterable should be a subtype of IterableOnce and 
> foreach loop should be retrofitted to work with IterableOnce.
> What do you think?
> Regards, Peter
> On 3/1/19 3:43 AM, Stuart Marks wrote:
>> Hi all,
>> Please review and comment on this proposal to allow Stream instances 
>> to be used in enhanced-for ("for-each") loops.
>> Abstract
>> Occasionally it's useful to iterate a Stream using a conventional 
>> loop. However, the Stream interface doesn't implement Iterable, and 
>> therefore streams cannot be used with the enhanced-for statement. 
>> This is a proposal to remedy that situation by introducing a new 
>> interface IterableOnce that is a subtype of Iterable, and then 
>> retrofitting the Stream interface to implement it. Other JDK classes 
>> will also be retrofitted to implement IterableOnce.
>> Full Proposal:
>> Bug report:
>> Webrev:
>> Note, this changeset isn't ready to push yet. In particular, it has 
>> no tests yet. However, the implementation is so simple that I figured 
>> I should include it. Comments on the specification wording are also 
>> welcome.
>> Thanks,
>> s'marks

More information about the core-libs-dev mailing list