Я провів розслідування в декількох списках розсилки лямбда проекту, і, думаю, знайшов кілька цікавих дискусій.
Я поки не знайшов задовільного пояснення. Прочитавши все це, я зробив висновок, що це був лише упущення. Але ви можете бачити, що це обговорювалося кілька років протягом проекту API.
Спеціалісти з ламбда-вуст
Я знайшов дискусію з цього приводу у списку розсилки спеціалістів Lambda Libs :
Під Iterable / Iterator.stream () Сем Пуллара сказав:
Я працював з Брайаном над тим, як бачити, як функція limit / substream [1] може бути реалізована, і він запропонував перейти до Iterator - це правильний шлях для цього. Я думав про це рішення, але не знайшов очевидного способу взяти ітератор і перетворити його на потік. Виявляється, це там, вам просто потрібно спершу перетворити ітератор у сплітератор, а потім перетворити сплітератор у потік. Отже, це змушує мене переглядати, чи повинні у нас відмовитися від одного з Iterable / Iterator безпосередньо або обох.
Моя пропозиція - принаймні мати його на Ітераторі, щоб ви могли чисто рухатися між двома світами, і це також було б легко виявити, а не робити:
Streams.stream (Spliterators.spliteratorUnknownSize (ітератор, Spliterator.ORDERED))
І тоді Брайан Гец відповів :
Я думаю, що Сем наголосив на тому, що існує багато бібліотечних класів, які дають вам ітератор, але не дозволяють вам обов'язково писати власний сплітератор. Отже, все, що ви можете зробити, це потік викликів (spliteratorUnknownSize (ітератор)). Сем пропонує запропонувати Iterator.stream () зробити це для вас.
Я хотів би зберегти потокові () та spliterator () методи як для бібліотечних авторів / досвідчених користувачів.
І пізніше
"З огляду на те, що писати Spliterator простіше, ніж писати Iterator, я вважаю за краще просто написати Spliterator замість Iterator (Iterator так 90-х років :)"
Ти, однак, тобі не вистачає точки. Існують мільйони класів, які вже передають вам Ітератор. І багато з них не готові до розбризкування.
Попередні дискусії у списку розсилки лямбда
Можливо, це не відповідь, яку ви шукаєте, але в списку розсилки Project Lambda це було коротко обговорено. Можливо, це допомагає сприяти більш широкій дискусії з цього питання.
Слова Брайана Геца під " Потіками з Iterable" :
Відступаючи ...
Існує маса способів створення потоку. Чим більше інформації ви маєте про опис елементів, тим більше функціональності та продуктивності може надати вам бібліотека потоків. Для того, щоб принаймні отримати більшість інформації, вони:
Ітератор
Ітератор + розмір
Сплитератор
Сплитератор, який знає його розмір
Сплитератор, який знає його розмір, і далі знає, що всі підрозколи знають їх розмір.
(Дехто може бути здивований, виявивши, що ми можемо отримати паралелізм навіть з німого ітератора в тих випадках, коли Q (робота на елемент) нетривіальний.)
Якщо у Iterable був метод stream (), він би просто загортав Iterator зі Spliterator, без інформації про розмір. Але більшість речей, які є Ітерабельними , мають інформацію про розмір. Що означає, що ми обслуговуємо дефіцитні потоки. Це не так добре.
Одним із недоліків практики, описаної Стівеном тут, щодо прийняття Iterable замість колекції, є те, що ви змушуєте речі проходити через «маленьку трубу» і, таким чином, відкидаючи інформацію про розмір, коли це може бути корисним. Це добре, якщо все, що ви робите, - цеБудьте, але якщо ви хочете зробити більше, краще, якщо ви зможете зберегти всю інформацію, яку ви хочете.
За замовчуванням, наданий Iterable, справді був би хитрим - він би відкинув розмір, навіть якщо переважна більшість інтерабелів знає цю інформацію.
Протиріччя?
Хоча, схоже, дискусія ґрунтується на змінах, проведених Експертною групою в початковому дизайні потоків, який спочатку базувався на ітераторах.
Тим не менш, цікаво помітити, що в інтерфейсі, як Collection, метод потоку визначається як:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Що може бути точно тим же кодом, який використовується в Iterable інтерфейсі.
Отже, саме тому я сказав, що ця відповідь, ймовірно, не є задовільною, але все ж цікава для обговорення.
Докази рефакторингу
Продовжуючи аналіз у списку розсилки, схоже, що метод splitIterator спочатку знаходився в інтерфейсі Collection, і в якийсь момент у 2013 році вони перемістили його до Iterable.
Потягніть splitIterator з колекції на Iterable .
Висновок / теорії?
Тоді ймовірність полягає в тому, що відсутність методу в Iterable - це лише упущення, оскільки, схоже, вони повинні були перенести метод потоку також, коли вони перемістили splitIterator з колекції на Iterable.
Якщо є інші причини, вони не є очевидними. Хтось інший має інші теорії?