Почему нет интерфейса для чего-то, что обеспечивает Stream <E>?
Чтобы не допустить, чтобы данные реализации не протекали, вместо того, чтобы возвращать, например, Collection<MyCoolObject>
, можно было бы реализовать Iterable<MyCoolObject>
, для чего потребовалось бы реализовать Iterator<T>
из интерфейса Iterable
. Таким образом, однако, структура внутренней структуры управляется, доступ к элементам осуществляется через Iterator
.
С Java 8 можно добавить Stream<MyCoolObject> stream()
в MyCoolObject
. (См. Также: рекомендации по поддержке stream
в книге Java 8 Lambdas). При добавлении метода это не сложно (и я прочитал Вопрос о Почему Iterable не предоставляет поток), кажется странным, что Java не добавила интерфейс для Streamable<T>
, чтобы отразить идею Iterable<T>
. (Ну, другое имя возможно, так как Streamable
существует для когда-либо используемого материала CORBA).
Я думаю, что я последовал за ответом о том, почему добавление stream
в Iterable
было потенциально проблематичным, но я не понимаю, почему интерфейс Streaming<T>
не мог быть предоставлен. Например, Collections
мог бы реализовать интерфейс Streaming<T>
, и он упростит для других объектов, что можно ожидать метод stream()
.
На основании ответа на упомянутый выше Вопрос, можно получить stream
из Iterable
через
Stream s = StreamSupport.stream(iter.spliterator(), false);
но это похоже на большую работу, учитывая, что MyObject
мог бы просто реализовать stream()
, чтобы позволить пользователю объекта
myObject.stream().filter(...).collect(...)
без промежуточного преобразования из итератора.
Есть ли причина отсутствия интерфейса для потоковой передачи объектов? Есть ли лучший подход, чем просто реализовать stream()
в MyCoolObject и позволить кому-то просмотреть Javadoc, чтобы они знали, что у него есть метод stream()
?
Или, вполне вероятно, я что-то не понимаю о подходе к Stream?
(Кроме того, я реализую stream()
в CoolObject, но затем забудьте реализовать parallelStream()
, что будет облегчено благодаря интерфейсу).
Ответы
Ответ 1
Это должно, вероятно, увеличить любые будущие ответы.
Я не знаю, почему вы думаете, что лучше вернуть Iterable<MyCoolObject>
, а не Collection<MyCoolObject>
. Это может скрыть подробности, и это создаст больше проблем.
В коллекции есть known size
, которая играет большую роль при расщеплении для параллельной обработки. Об этом сообщается как Spliterator.SIZED | Spliterator.SUBSIZED
. Таким образом, Collection.stream
будет обрабатывать параллельные потоки намного лучше, чем Iterable
, которые будут использовать:
public static <T> Spliterator<T> spliteratorUnknownSize
который документируется как:
... и реализует trySplit для разрешения ограниченного parallelism.
Это очевидно, так как вы вообще не знаете размер. В текущей реализации размер партии 1024
. Так, например, для чего-либо менее 1024 элементов вы не получите никакой параллелизации вообще.
Теперь, насколько ваш вопрос идет, в ранних сборках jdk-8 это было так. Он назывался java.util.stream.Streamable
. Из того, что я знаю, оно было удалено, потому что есть методы, возвращающие Stream
, но не через метод stream()
.
String::codePoints()
File::lines
Pattern::splitAsStream
... many others
Таким образом, единственным местом, где это будет реализовано, будет сбор. И это, насколько я могу судить, было бы действительно изолированным местом.
Аха момент
Ниже приведено объяснение от людей, ответственных за это.
Как показано здесь, причины устранения:
Я рассматриваю возможность отключения интерфейса Streamable. В настоящее время Реализация - это сборник, и все другие потоковые методы обслуживают специализированные потоки (chars(), codePoints(), lines() и т.д.), с именем метода, которое более подходит, чем "поток". Поэтому я думаю, что мы следует отключить Streamable и оставить методы stream()/parallel() на Коллекция (или, возможно, переместить их в Iterable).
Ответ 2
Поскольку он был удален, но вы можете легко реализовать свою собственную реализацию Streamable
, если вам это нужно:
@FunctionalInterface
interface Streamable<T> {
Stream<T> stream();
}
Если мы возьмем пример шаблона стратегии, вы тогда определите его так:
interface StreamStrategy<T> {
Streamable<T> getStreamable();
}
который может быть легко реализован на основе любого объекта поддержки, предоставляющего метод, возвращающий Stream<T>
, используя ссылку на метод. Например, если у вас есть коллекция:
class CollectionBasedStrategy<T> implements StreamStrategy<T> {
@Override
public Streamable<T> getStreamable() {
return new ArrayList<T>()::stream;
}
}
Если Collection
расширяет такой интерфейс Streamable
, вам действительно не нужно использовать ссылку на метод. Но в противном случае, похоже, не было много добавленной ценности, чтобы поместить это в JDK - и при необходимости он может быть добавлен позже.