Я провел расследование в нескольких лямбда-рассылках проекта, и, думаю, нашел несколько интересных обсуждений.
Я не нашел удовлетворительного объяснения до сих пор. Прочитав все это, я пришел к выводу, что это просто упущение. Но вы можете видеть здесь, что это обсуждалось несколько раз за годы разработки API.
Специалисты по Lambda Libs Spec
Я нашел обсуждение этого вопроса в списке рассылки Lambda Libs Spec Experts :
Под Iterable / Iterator.stream () Сэм Пуллара сказал:
Я работал с Брайаном над тем, чтобы увидеть, как может быть реализована функциональность limit / substream [1], и он предположил, что преобразование в Iterator - это правильный путь. Я думал об этом решении, но не нашел очевидного способа взять итератор и превратить его в поток. Оказывается, он там, вам просто нужно сначала преобразовать итератор в сплитератор, а затем преобразовать сплитератор в поток. Таким образом, это заставляет меня вернуться к вопросу о том, должны ли они зависать от одного из Iterable / Iterator напрямую или от обоих.
Я предлагаю по крайней мере иметь его на Iterator, чтобы вы могли аккуратно перемещаться между двумя мирами, и это также было бы легко обнаружить, вместо того, чтобы делать это:
Streams.stream (Spliterators.spliteratorUnknownSize (iterator, Spliterator.ORDERED))
И тогда Брайан Гетц ответил :
Я думаю, что Сэм имел в виду, что существует множество библиотечных классов, которые дают вам Итератор, но не позволяют вам обязательно написать свой собственный сплитератор. Поэтому все, что вы можете сделать, это вызвать поток (spliteratorUnknownSize (iterator)). Сэм предлагает, чтобы мы определили Iterator.stream (), чтобы сделать это для вас.
Я хотел бы сохранить методы stream () и spliterator () как для авторов библиотек / опытных пользователей.
И позже
«Учитывая, что написание Spliterator проще, чем написание итератора, я бы предпочел просто написать Spliterator вместо итератора (итератор - это 90-е годы :)»
Вы упускаете суть, хотя. Есть миллионы классов, которые уже вручают вам Итератор. И многие из них не готовы к разделению.
Предыдущие обсуждения в списке рассылки Lambda
Возможно, это не тот ответ, который вы ищете, но в списке рассылки Project Lambda это было кратко обсуждено. Возможно, это помогает стимулировать более широкую дискуссию на эту тему.
По словам Брайана Гетца в разделе « Потоки из Итерибла» :
Отступая ...
Есть много способов создать поток. Чем больше у вас информации о том, как описать элементы, тем больше функциональности и производительности может предоставить библиотека потоков. В порядке наименьшего количества информации они:
Итератор
Итератор + размер
Spliterator
Spliterator, который знает его размер
Spliterator, который знает его размер, и, кроме того, знает, что все подразделы знают свой размер.
(Некоторые могут удивиться, обнаружив, что мы можем извлечь параллелизм даже из тупого итератора в тех случаях, когда Q (работа на элемент) нетривиальна.)
Если бы Iterable имел метод stream (), он просто обернул бы Iterator Spliterator без информации о размере. Но большинство вещей, которые являются Iterable , имеют информацию о размере. Что означает, что мы обслуживаем несовершенные потоки. Это не так хорошо.
Одним из недостатков практики API, изложенной здесь Стивеном, в принятии Iterable вместо Collection, является то, что вы проталкиваете вещи через «маленький канал» и, следовательно, отбрасываете информацию о размере, когда это может быть полезно. Это хорошо, если все, что вы делаете, это для каждого, но если вы хотите сделать больше, лучше, если вы сможете сохранить всю информацию, которую вы хотите.
Значение по умолчанию, предоставляемое Iterable, было бы поистине дрянным - оно отбросило бы размер, даже если подавляющее большинство Iterables знают эту информацию.
Противоречие?
Хотя, похоже, что обсуждение основано на изменениях, которые Группа экспертов внесла в первоначальный дизайн Streams, который изначально был основан на итераторах.
Тем не менее, интересно отметить, что в интерфейсе, подобном Collection, метод stream определяется как:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Это может быть тот же код, который используется в интерфейсе Iterable.
Вот почему я сказал, что этот ответ, вероятно, не является удовлетворительным, но все же интересным для обсуждения.
Свидетельство Рефакторинга
Продолжая анализ в списке рассылки, похоже, что метод splitIterator изначально был в интерфейсе Collection, и в какой-то момент в 2013 году они переместили его в Iterable.
Вытяните splitIterator из коллекции в итерируемую .
Заключение / Теории?
Тогда есть вероятность, что отсутствие метода в Iterable является просто упущением, поскольку похоже, что они должны были также переместить потоковый метод, когда они переместили splitIterator из Collection в Iterable.
Если есть другие причины, они не очевидны. У кого-то еще есть другие теории?