В Java 8 у нас есть класс Stream <T> , который, как ни странно, имеет метод
Iterator<T> iterator()
Таким образом, вы ожидаете, что он реализует интерфейс Iterable <T> , который требует именно этот метод, но это не так.
Когда я хочу перебрать поток с помощью цикла foreach, я должен сделать что-то вроде
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Я что-то здесь упускаю?
Stream
к устаревшим API, которые ожидаютIterable
getIterable()
доreturn s::iterator;
for (T element : stream::iterator)
, поэтому я все же предпочел бы, чтобы Stream также реализовывалIterable
или методtoIterable()
.Ответы:
Люди уже спрашивали то же самое в списке рассылки ☺. Основная причина в том, что Iterable также имеет повторяемую семантику, а Stream - нет.
источник
Iterable
о том,iterator
должен ли он быть всегда или не вызываться несколько раз. Это то, что они должны положить туда. Кажется, это больше стандартная практика, чем формальная спецификация.Чтобы преобразовать
Stream
вIterable
, вы можете сделатьЧтобы передать
Stream
метод, который ожидаетIterable
,просто
однако это, вероятно, выглядит смешно; было бы лучше быть немного более явным
источник
for(X x : (Iterable<X>)stream::iterator)
, хотя это выглядит некрасиво. Действительно, вся ситуация просто абсурдна.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
иstream.iterator()
, что делает бывший приемлемым для ,Iterable
но не последний?Iterable
это функциональный интерфейс, поэтому достаточно передать функцию, которая его реализует.Я хотел бы отметить, что
StreamEx
реализуетIterable
(иStream
), а также множество других очень удивительных функциональных возможностей, отсутствующих вStream
.источник
Вы можете использовать Stream в
for
цикле следующим образом:(Запустите этот фрагмент здесь )
(При этом используется функциональный интерфейс Java 8).
(Это описано в некоторых комментариях выше (например, Александр Дубинский ), но я хотел вытащить его в ответ, чтобы сделать его более заметным.)
источник
Кеннитм описал, почему небезопасно относиться к a
Stream
как кIterable
, и Чжун Ю предложил обходной путь, который позволяет использовать aStream
in inIterable
, хотя и небезопасным образом. Можно получить лучшее из обоих миров: многоразовогоIterable
использования,Stream
которое отвечает всем гарантиям, указанным вIterable
спецификации.Примечание:
SomeType
здесь не параметр типа - вам нужно заменить его на правильный тип (например,String
) или прибегнуть к отражениюЕсть один главный недостаток:
Преимущества ленивой итерации будут потеряны. Если вы планировали немедленно выполнить итерацию по всем значениям в текущем потоке, любые издержки будут незначительными. Однако, если вы планируете выполнять итерацию только частично или в другом потоке, эта немедленная и полная итерация может иметь непредвиденные последствия.
Большим преимуществом, конечно, является то, что вы можете повторно использовать
Iterable
, тогда как(Iterable<SomeType>) stream::iterator
разрешить только одно использование. Если принимающий код будет перебирать коллекцию несколько раз, это не только необходимо, но, скорее всего, полезно для производительности.источник
Stream.toArray()
возвращает массив, а не anIterable
, поэтому этот код по-прежнему не компилируется. но это может быть ошибкой в затмении, так как IntelliJ, кажется, компилирует егоStream
не реализуетIterable
. Общее пониманиеIterable
- это все, что можно повторять, часто снова и снова.Stream
может не воспроизводитьсяЕдинственный обходной путь, который я могу придумать, когда итерация, основанная на потоке, также может быть воспроизведена, - это воссоздать поток. Я использую
Supplier
ниже для создания нового экземпляра потока, каждый раз, когда создается новый итератор.источник
Если вы не возражаете против использования сторонних библиотек, циклоп-реакция определяет поток, который реализует оба потока и итерируемый, а также воспроизводимый (решение проблемы описанной kennytm ).
или :-
[Раскрытие Я ведущий разработчик циклоп-реакции]
источник
Не идеально, но будет работать:
Не совершенным , потому что он будет получать все элементы из потока и поместить их в том , что
List
, что это не совсем то , чтоIterable
иStream
о. Они должны быть ленивыми .источник
Вы можете перебирать все файлы в папке
Stream<Path>
следующим образом:источник