Comment itérer sur un flux avec des indices

Comment itérer sur un flux avec des indices

1. Vue d'ensemble

Java 8Streams ne sont pas des collections et les éléments ne sont pas accessibles à l'aide de leurs index, mais il existe encore quelques astuces pour rendre cela possible.

Dans ce court article, nous allons voir comment itérer sur unStream en utilisantIntStream,StreamUtils, EntryStream, etVavrStream.

2. Utilisation de Java brut

On peut naviguer à travers unStream en utilisant une plageInteger, et aussi profiter du fait que les éléments originaux sont dans un tableau ou une collection accessible par des indices.

Implémentons une méthode qui itère avec des index et démontre cette approche.

En termes simples, nous voulons obtenir un tableau deStrings et ne sélectionner que les éléments même indexés:

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;
}

Testons maintenant la mise en œuvre:

@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. Utilisation deStreamUtils

Une autre façon d'itérer avec les index peut être faite en utilisant la méthodezipWithIndex() deStreamUtils de la bibliothèqueproton-pack (la dernière version peut être trouvéehere).

Tout d'abord, vous devez l'ajouter à vospom.xml:


    com.codepoetics
    protonpack
    1.13

Examinons maintenant le code:

public List> getEvenIndexedStrings(List names) {
    List> list = StreamUtils
      .zipWithIndex(names.stream())
      .filter(i -> i.getIndex() % 2 == 0)
      .collect(Collectors.toList());

    return list;
}

Ce qui suit teste cette méthode et réussit:

@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. Utilisation deStreamEx

Nous pouvons également itérer avec des index en utilisantfilterKeyValue() de la classeEntryStream de la bibliothèqueStreamEx (la dernière version peut être trouvéehere). Tout d'abord, nous devons l'ajouter à nospom.xml:


    one.util
    streamex
    0.6.5

Voyons une application simple de cette méthode en utilisant notre exemple précédent:

public List getEvenIndexedStringsVersionTwo(List names) {
    return EntryStream.of(names)
      .filterKeyValue((index, name) -> index % 2 == 0)
      .values()
      .toList();
}

Nous allons utiliser un test similaire pour tester ceci:

@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. Itération utilisant Vavre deStream

Une autre manière plausible d'itération consiste à utiliser la méthodezipWithIndex() de l'implémentationStream deVavr (anciennement connue sous le nom deJavaslang):

public List getOddIndexedStringsVersionTwo(String[] names) {
    return Stream
      .of(names)
      .zipWithIndex()
      .filter(tuple -> tuple._2 % 2 == 1)
      .map(tuple -> tuple._1)
      .toJavaList();
}

Nous pouvons tester cet exemple avec la méthode suivante:

@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);
}

Si vous voulez en savoir plus sur Vavr,check this article.

6. Conclusion

Dans ce didacticiel rapide, nous avons vu quatre approches sur la façon de parcourir des flux à l’aide d’index. Les flux ont attiré beaucoup d'attention et il peut être utile de pouvoir les parcourir avec des index.

De nombreuses fonctionnalités sont incluses dans Java 8 Streams, dont certaines sont déjà couvertes surexample.

Le code de tous les exemples expliqués ici, et bien plus encore, peut être trouvéover on GitHub.