Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Iterable<T> not provide stream() and parallelStream() methods?

I am wondering why the Iterable interface does not provide the stream() and parallelStream() methods. Consider the following class:

public class Hand implements Iterable<Card> {     private final List<Card> list = new ArrayList<>();     private final int capacity;      //...      @Override     public Iterator<Card> iterator() {         return list.iterator();     } } 

It is an implementation of a Hand as you can have cards in your hand while playing a Trading Card Game.

Essentially it wraps a List<Card>, ensures a maximum capacity and offers some other useful features. It is better as implementing it directly as a List<Card>.

Now, for convienience I thought it would be nice to implement Iterable<Card>, such that you can use enhanced for-loops if you want to loop over it. (My Hand class also provides a get(int index) method, hence the Iterable<Card> is justified in my opinion.)

The Iterable interface provides the following (left out javadoc):

public interface Iterable<T> {     Iterator<T> iterator();      default void forEach(Consumer<? super T> action) {         Objects.requireNonNull(action);         for (T t : this) {             action.accept(t);         }     }      default Spliterator<T> spliterator() {         return Spliterators.spliteratorUnknownSize(iterator(), 0);     } } 

Now can you obtain a stream with:

Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false); 

So onto the real question:

  • Why does Iterable<T> not provide a default methods that implement stream() and parallelStream(), I see nothing that would make this impossible or unwanted?

A related question I found is the following though: Why does Stream<T> not implement Iterable<T>?
Which is oddly enough suggesting it to do it somewhat the other way around.

like image 235
skiwi Avatar asked Apr 16 '14 15:04

skiwi


People also ask

Can you stream an Iterable?

The Iterable interface is designed keeping generality in mind and does not provide any stream() method on its own. Simply put, you can pass it to StreamSupport. stream() method and get a Stream from the given Iterable instance.

How do you filter Iterable?

To perform the filtering process, filter() applies function to every item of iterable in a loop. The result is an iterator that yields the values of iterable for which function returns a true value. The process doesn't modify the original input iterable.

What is StreamSupport in Java?

public final class StreamSupport extends Object. Low-level utility methods for creating and manipulating streams. This class is mostly for library writers presenting stream views of data structures; most static stream methods intended for end users are in the various Stream classes.


1 Answers

This was not an omission; there was detailed discussion on the EG list in June of 2013.

The definitive discussion of the Expert Group is rooted at this thread.

While it seemed "obvious" (even to the Expert Group, initially) that stream() seemed to make sense on Iterable, the fact that Iterable was so general became a problem, because the obvious signature:

Stream<T> stream() 

was not always what you were going to want. Some things that were Iterable<Integer> would rather have their stream method return an IntStream, for example. But putting the stream() method this high up in the hierarchy would make that impossible. So instead, we made it really easy to make a Stream from an Iterable, by providing a spliterator() method. The implementation of stream() in Collection is just:

default Stream<E> stream() {     return StreamSupport.stream(spliterator(), false); } 

Any client can get the stream they want from an Iterable with:

Stream s = StreamSupport.stream(iter.spliterator(), false); 

In the end we concluded that adding stream() to Iterable would be a mistake.

like image 100
Brian Goetz Avatar answered Oct 11 '22 23:10

Brian Goetz