1. 概要

この簡単な記事では、要素をJava 8 Stream に追加する方法を見ていきます。これは、通常のコレクションに要素を追加するほど直感的ではありません。

2. プリペンディング

静的なStream。concat()メソッドを呼び出すことにより、特定の要素をStreamの前に簡単に追加できます。

@Test
public void givenStream_whenPrependingObject_thenPrepended() {
    Stream<Integer> anStream = Stream.of(1, 2, 3, 4, 5);

    Stream<Integer> newStream = Stream.concat(Stream.of(99), anStream);

    assertEquals(newStream.findFirst().get(), (Integer) 99);
}

3. 追加

同様に、 Stream、の最後に要素を追加するには、引数を反転する必要があります。

ストリームは無限のシーケンスを表すことができるため、新しい要素に到達できないシナリオがあります。

@Test
public void givenStream_whenAppendingObject_thenAppended() {
    Stream<String> anStream = Stream.of("a", "b", "c", "d", "e");

    Stream<String> newStream = Stream.concat(anStream, Stream.of("A"));

    List<String> resultList = newStream.collect(Collectors.toList());
 
    assertEquals(resultList.get(resultList.size() - 1), "A");
}

4. 特定のインデックスで

Stream (java.util.stream) in Java is a sequence of elements supporting sequential and parallel aggregate operations. There is no function for adding a value to a specific index since it’s not designed for such a thing. However, there are a couple of ways to achieve it.

One approach is to use a terminal operation to collect the values of the stream to an ArrayList, and then simply use add(int index, E element) method. Keep in mind that this will give you the desired result but you will also lose the laziness of a Stream because you need to consume it before inserting a new element.

The alternative is to use Spliterator and iterate the elements sequentially to the target index (using the iterator of the Spliterator class.) The concept is to break the stream into two streams (A and B). Stream A starts from index 0 to the target index, and stream B is the remaining element. Then add the element to stream A, and finally concatenate streams A and B.

In this case, since the stream is not consumed greedily, it is still partially lazy:

private static  Stream insertInStream(Stream stream, T elem, int index) {
    Spliterator spliterator = stream.spliterator();
    Iterator iterator = Spliterators.iterator(spliterator);

    return Stream.concat(Stream.concat(Stream.generate(iterator::next)
      .limit(index), Stream.of(elem)), StreamSupport.stream(spliterator, false));
}

それでは、コードをテストして、すべてが期待どおりに機能していることを確認しましょう。

@Test
public void givenStream_whenInsertingObject_thenInserted() {
    Stream<Double> anStream = Stream.of(1.1, 2.2, 3.3);
    Stream<Double> newStream = insertInStream(anStream, 9.9, 3);

    List<Double> resultList = newStream.collect(Collectors.toList());
 
    assertEquals(resultList.get(3), (Double) 9.9);
}

5. 結論

この短い記事では、ストリームに単一の要素を追加する方法を説明しました。は、最初、最後、または特定の位置にあります。

要素の先頭に追加することはStreamに対して機能しますが、を末尾または特定のインデックスに追加することは、有限のストリームに対してのみ機能することに注意してください。

いつものように、完全なソースコードはGithubにあります。