1. 概要

Java 8 Streams はコレクションではなく、インデックスを使用して要素にアクセスすることはできませんが、これを可能にするためのいくつかのトリックがあります。

この短い記事では、 IntStream、 StreamUtils、EntryStream、Vavrを使用してStreamを反復処理する方法を見ていきます。 ]のストリーム

2. プレーンJavaの使用

Integer の範囲を使用して、 Stream をナビゲートできます。また、元の要素が配列内にあるか、インデックスからアクセスできるコレクションであるという利点もあります。

インデックスを使用して反復し、このアプローチを示すメソッドを実装してみましょう。

簡単に言えば、 Strings の配列を取得し、インデックス付きの要素のみを選択する必要があります。

public List<String> getEvenIndexedStrings(String[] names) {
    List<String> evenIndexedNames = IntStream
      .range(0, names.length)
      .filter(i -> i % 2 == 0)
      .mapToObj(i -> names[i])
      .collect(Collectors.toList());
    
    return evenIndexedNames;
}

次に、実装をテストしてみましょう。

@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Afrim", "Besim", "Durim");
    List<String> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
   
    assertEquals(expectedResult, actualResult);
}

3. StreamUtilsを使用する

インデックスを反復処理する別の方法は、プロトンパックライブラリの StreamUtilszipWithIndex()メソッドを使用して実行できます(最新バージョンはにあります)。ここ)。

まず、それをyour pom.xmlに追加する必要があります。

<dependency>
    <groupId>com.codepoetics</groupId>
    <artifactId>protonpack</artifactId>
    <version>1.13</version>
</dependency>

それでは、コードを見てみましょう。

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

以下は、このメソッドをテストし、正常に合格します。

@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
    List<String> names = Arrays.asList(
      "Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim");
    List<Indexed<String>> expectedResult = Arrays.asList(
      Indexed.index(0, "Afrim"), 
      Indexed.index(2, "Besim"), 
      Indexed.index(4, "Durim"));
    List<Indexed<String>> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
    
    assertEquals(expectedResult, actualResult);
}

4. StreamExを使用する

StreamExライブラリのEntryStreamクラスのfilterKeyValue()を使用してインデックスを反復処理することもできます(最新バージョンはここにあります)。 まず、それを pom.xml:に追加する必要があります

<dependency>
    <groupId>one.util</groupId>
    <artifactId>streamex</artifactId>
    <version>0.6.5</version>
</dependency>

前の例を使用して、このメソッドの簡単なアプリケーションを見てみましょう。

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

同様のテストを使用して、これをテストします。

@Test
public void whenCalled_thenReturnListOfEvenIndexedStringsVersionTwo() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Afrim", "Besim", "Durim");
    List<String> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
   
   assertEquals(expectedResult, actualResult);
}

5. を使用した反復 Vavreストリーム

反復のもう1つのもっともらしい方法は、 Vavr (以前は Javaslang と呼ばれていました)の Stream実装のzipWithIndex()メソッドを使用することです。

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

この例は、次の方法でテストできます。

@Test
public void whenCalled_thenReturnListOfOddStringsVersionTwo() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Bashkim", "Lulzim", "Shpetim");
    List<String> actualResult 
      = StreamIndices.getOddIndexedStringsVersionTwo(names);

    assertEquals(expectedResult, actualResult);
}

Vavrについて詳しく知りたい場合は、この記事を確認してください。

6. 結論

このクイックチュートリアルでは、インデックスを使用してストリームを反復処理する方法について4つのアプローチを見ました。 ストリームは多くの注目を集めており、インデックスを使用してストリームを反復処理できると便利です。

Java 8 Streamsには多くの機能が含まれており、そのうちのいくつかはBaeldungですでにカバーされています。

ここで説明されているすべての例のコード、およびその他の多くのコードは、GitHubにあります。