Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8272137

Make Iterable classes streamable




      n/a. This request for enhancement is system/OS/JRT independent.

      At the moment `Collection<E>` implements stream and parallelStream. This implementation only depends on the existence of the StreamSupport.stream() static method and the spliterator method provided by the Iterable<E> class.

      Unfortunately, the stream and parallelStream methods aren't defined in Iterable<E>, so if you want to create a stream you'd need to manually call StreamSupport.stream(iterable.spliterator(), true/false) if you want a stream.

      It would be nice if you could in some way stream iterables more conveniently. There is multiple options:

      1. Create abstract methods for stream and parallelStream in Iterable<E>. The disadvantage for this is that all implementing classes would now have to implement these methods and therefore make this a breaking change, which is not desirable.

      2. Move the stream and parallelStream method implementation from Collection<E> to Iterable<E>: this would mean that all classes that implement Iterable<E> still are valid, but it also exposes these extra methods. It would require an impact analysis to see if any security issues could arise from this.

      3. Create a new interface Streamable<E> that extends Iterable<E>, where the stream and parallelStream methods are defined. It wouldn't matter if they were abstract or not here. Both could work. This would allow API's that now return an Iterable<E> to return a Streamable<E> instead, when applicable. Iterable itself would not need to change in this case, however it would require APIs to update if they want to provide the option to stream without StreamSupport.

      4. Create a Streamable<E> interface that doesn't inherit anything and specifies the abstract stream and parallelStream methods. The implementation could still be left to the classes that implement it/interfaces that extend it like Collection<E>. The benefit over option 3 is that it follows the Interface Segregation Principle better. The disadvantage is that to be able to take advantage of both the iterability and streamability on a value returned from an API, it'd need to use an interface or concrete class that extends/implements both, like Collection<E>, or you'd need to make the method that returns this value generic like:

      public <T extends Iterable<E> & Streamable<E>> T getValues() { ... }

      I myself am leaning towards option 3 or 4. The 4th option seems cleaner, but has the described disadvantage of requiring generics or a class/interface that is both iterable and streamable. I think the decision would depend on whether there would be any streamable objects that aren't also iterable.

      Possible applications in APIs would include for example the findAll method in a Hibernate repository. It returns an Iterable<E> instead of a Collection<E> or List<E>. Therefore you can't just call the stream or parallelStream method on these objects. It might also be too restrictive for the API to return a Collection<E>, since they might implement their own Iterable for performance optimizations. In this case it would be nice if the findAll could have the returntype Streamable or <T extends Iterable & Streamable> T, depending on whether option 3 or 4 was chosen.


          Issue Links



              Unassigned Unassigned
              webbuggrp Webbug Group
              0 Vote for this issue
              7 Start watching this issue