No Java 8, temos a classe Stream <T> , que curiosamente tem um método
Iterator<T> iterator()
Então, você esperaria implementar a interface Iterable <T> , que requer exatamente esse método, mas esse não é o caso.
Quando quero iterar em um Stream usando um loop foreach, tenho que fazer algo como
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)) { ... }
Estou faltando alguma coisa aqui?
java
java-8
java-stream
iterable
roim
fonte
fonte
Stream
para APIs de legado que esperaIterable
getIterable()
quereturn s::iterator;
for (T element : stream::iterator)
, por isso ainda prefiro se o Stream também implementariaIterable
ou um métodotoIterable()
.Respostas:
As pessoas já perguntaram o mesmo na lista de discussão ☺. O principal motivo é que o Iterable também possui uma semântica reiterável, enquanto o Stream não.
fonte
Iterable
sobre seiterator
deve ou não ser possível chamar várias vezes. Isso é algo que eles deveriam colocar lá. Isso parece ser mais uma prática padrão do que uma especificação formal.Para converter um
Stream
para umIterable
, você pode fazerPara passar a
Stream
para um método que esperaIterable
,simplesmente
no entanto, provavelmente parece engraçado; pode ser melhor ser um pouco mais explícito
fonte
for(X x : (Iterable<X>)stream::iterator)
, embora pareça feio. Realmente, toda a situação é simplesmente absurda.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
estream.iterator()
, que torna o primeiro aceitável para um,Iterable
mas não o último?Iterable
é uma interface funcional; basta passar uma função que a implementa.Gostaria de salientar que
StreamEx
implementaIterable
(eStream
), bem como uma série de outras funcionalidades imensamente impressionantes ausentesStream
.fonte
Você pode usar um fluxo em um
for
loop da seguinte maneira:(Execute este trecho aqui )
(Isso usa uma interface funcional Java 8 convertida.)
(Isso é abordado em alguns dos comentários acima (por exemplo, Aleksandr Dubinsky ), mas eu queria extraí-lo em uma resposta para torná-lo mais visível.)
fonte
O kennytm descreveu por que não é seguro tratar um
Stream
como umIterable
e Zhong Yu oferece uma solução alternativa que permite o uso de umStream
comoIterable
, embora de maneira insegura. É possível obter o melhor dos dois mundos: a reutilizáveisIterable
a partir de umStream
que atenda todas as garantias feitas pelaIterable
especificação.Nota:
SomeType
não é um parâmetro de tipo aqui - você precisa substituí-lo por um tipo adequado (por exemplo,String
) ou recorrer à reflexãoHá uma grande desvantagem:
Os benefícios da iteração lenta serão perdidos. Se você planejou iterar imediatamente todos os valores no encadeamento atual, qualquer sobrecarga será insignificante. No entanto, se você planejou iterar apenas parcialmente ou em um encadeamento diferente, essa iteração imediata e completa pode ter consequências indesejadas.
A grande vantagem, é claro, é que você pode reutilizar o
Iterable
, enquanto(Iterable<SomeType>) stream::iterator
isso permitiria apenas um único uso. Se o código de recebimento estiver repetindo a coleção várias vezes, isso não é apenas necessário, mas provavelmente benéfico para o desempenho.fonte
Stream.toArray()
retorna uma matriz, não umaIterable
, portanto esse código ainda não é compilado. mas pode ser um bug no eclipse, desde IntelliJ parece compilá-loStream
não implementaIterable
. O entendimento geral deIterable
qualquer coisa que possa ser repetido, muitas e muitas vezes.Stream
pode não ser reproduzível.A única solução alternativa em que consigo pensar, em que uma iterável baseada em um fluxo também é reproduzível, é recriar o fluxo. Estou usando um
Supplier
abaixo para criar uma nova instância do fluxo, sempre que um novo iterador é criado.fonte
Se você não se importa em usar bibliotecas de terceiros, o cyclops- react define um Stream que implementa Stream e Iterable e também é reproduzível (resolvendo o problema descrito pelo kennytm ).
ou: -
[Divulgação Sou o principal desenvolvedor do cyclops-react]
fonte
Não é perfeito, mas funcionará:
Não é perfeito porque ele buscará todos os itens do fluxo e os colocará nele
List
, o que não é exatamente o que éIterable
e o queStream
é. Eles deveriam ser preguiçosos .fonte
Você pode iterar sobre todos os arquivos em uma pasta usando o
Stream<Path>
seguinte:fonte