Como iterar sobre um fluxo com índices
1. Visão geral
Java 8Streams não são coleções e os elementos não podem ser acessados usando seus índices, mas ainda existem alguns truques para tornar isso possível.
Neste breve artigo, veremos como iterar emStream usandoIntStream,StreamUtils, EntryStream,eVavrStream.
2. Usando Plain Java
Podemos navegar porStream usando um intervaloInteger, e também nos beneficiar do fato de que os elementos originais estão em um array ou coleção acessível por índices.
Vamos implementar um método que itera com índices e demonstra essa abordagem.
Simplificando, queremos obter uma matriz deStringse selecionar apenas elementos indexados:
public List getEvenIndexedStrings(String[] names) {
List evenIndexedNames = IntStream
.range(0, names.length)
.filter(i -> i % 2 == 0)
.mapToObj(i -> names[i])
.collect(Collectors.toList());
return evenIndexedNames;
}
Agora vamos testar a implementação:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Afrim", "Besim", "Durim");
List actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
3. UsandoStreamUtils
Outra maneira de iterar com índices pode ser feita usando o métodozipWithIndex() deStreamUtils da bibliotecaproton-pack (a versão mais recente pode ser encontradahere).
Primeiro, você precisa adicioná-lo ao seupom.xml:
com.codepoetics
protonpack
1.13
Agora, vamos dar uma olhada no código:
public List> getEvenIndexedStrings(List names) {
List> list = StreamUtils
.zipWithIndex(names.stream())
.filter(i -> i.getIndex() % 2 == 0)
.collect(Collectors.toList());
return list;
}
O seguinte testa esse método e passa com êxito:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
List names = Arrays.asList(
"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim");
List> expectedResult = Arrays.asList(
Indexed.index(0, "Afrim"),
Indexed.index(2, "Besim"),
Indexed.index(4, "Durim"));
List> actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
4. UsandoStreamEx
Também podemos iterar com índices usandofilterKeyValue() da classeEntryStream da bibliotecaStreamEx (a versão mais recente pode ser encontradahere). Primeiro, precisamos adicioná-lo ao nossopom.xml:
one.util
streamex
0.6.5
Vamos ver uma aplicação simples desse método usando nosso exemplo anterior:
public List getEvenIndexedStringsVersionTwo(List names) {
return EntryStream.of(names)
.filterKeyValue((index, name) -> index % 2 == 0)
.values()
.toList();
}
Usaremos um teste semelhante para testar isso:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStringsVersionTwo() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Afrim", "Besim", "Durim");
List actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
5. Iteração usando Vavre'sStream
Outra forma plausível de iteração é usar o métodozipWithIndex() deVavr (anteriormente conhecido comoJavaslang) da implementaçãoStream:
public List getOddIndexedStringsVersionTwo(String[] names) {
return Stream
.of(names)
.zipWithIndex()
.filter(tuple -> tuple._2 % 2 == 1)
.map(tuple -> tuple._1)
.toJavaList();
}
Podemos testar este exemplo com o seguinte método:
@Test
public void whenCalled_thenReturnListOfOddStringsVersionTwo() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Bashkim", "Lulzim", "Shpetim");
List actualResult
= StreamIndices.getOddIndexedStringsVersionTwo(names);
assertEquals(expectedResult, actualResult);
}
Se você quiser ler mais sobre Vavr,check this article.
6. Conclusão
Neste tutorial rápido, vimos quatro abordagens sobre como iterar através de fluxos usando índices. Os fluxos receberam muita atenção e a possibilidade de iterar através deles com índices pode ser útil.
Muitos recursos estão incluídos no Java 8 Streams, alguns dos quais já estão incluídos emexample.
O código para todos os exemplos explicados aqui e muito mais pode ser encontradoover on GitHub.