合併Java流
1.概述
在這篇快速文章中,我們解釋了合併Java Streams
不同方法-這不是一個非常直觀的操作。
2.使用純Java
JDK 8 Stream
類具有一些有用的靜態實用程序方法。讓我們仔細看一下concat()
方法。
2.1。合併兩個Streams
組合2個Stream
的最簡單方法是使用靜態Stream.concat()
方法:
@Test
public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> resultingStream = Stream.concat(stream1, stream2);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6),
resultingStream.collect(Collectors.toList()));
}
2.2。合併多個Stream
當我們需要合併兩個以上的Streams,
事情會變得更加複雜。一種可能是連接前兩個流,然後將結果與下一個流連接,依此類推。
下一個代碼片段顯示了這一操作:
@Test
public void given3Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> resultingStream = Stream.concat(
Stream.concat(stream1, stream2), stream3);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36),
resultingStream.collect(Collectors.toList()));
}
如我們所見,這種方法對於更多的流來說是不可行的。當然,我們可以創建中間變量或輔助方法以使其更具可讀性,但這是一個更好的選擇:
@Test
public void given4Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> stream4 = Stream.of(99);
Stream<Integer> resultingStream = Stream.of(
stream1, stream2, stream3, stream4)
.flatMap(i -> i);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99),
resultingStream.collect(Collectors.toList()));
}
這裡發生的是:
- 我們首先創建一個包含4個
Streams,
的新Stream
Streams,
這將導致Stream<Stream<Integer>>
- 然後,我們使用identity函數將其
flatMap()
轉換為Stream<Integer>
3.使用StreamEx
StreamEx是一個開源Java庫,它擴展了Java 8 Streams的可能性。它使用StreamEx
類作為對JDK的Stream
接口的增強。
3.1。合併Stream
StreamEx庫允許我們使用append()
實例方法合併流:
@Test
public void given4Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> stream4 = Stream.of(99);
Stream<Integer> resultingStream = StreamEx.of(stream1)
.append(stream2)
.append(stream3)
.append(stream4);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99),
resultingStream.collect(Collectors.toList()));
}
由於它是一個實例方法,因此我們可以輕鬆地將其鏈接並追加多個流。
需要注意的是,我們還可以創建一個List
,通過使用出流的toList()
如果我們鍵入resultingStream
變量的StreamEx
類型。
3.2。使用prepend()
合併流
StreamEx還包含一種在元素之間添加元素的方法,稱為prepend()
:
@Test
public void given3Streams_whenPrepended_thenResultStreamContainsAllElements() {
Stream<String> stream1 = Stream.of("foo", "bar");
Stream<String> openingBracketStream = Stream.of("[");
Stream<String> closingBracketStream = Stream.of("]");
Stream<String> resultingStream = StreamEx.of(stream1)
.append(closingBracketStream)
.prepend(openingBracketStream);
assertEquals(
Arrays.asList("[", "foo", "bar", "]"),
resultingStream.collect(Collectors.toList()));
}
4.使用Jooλ
jOOλ是JDK 8兼容的庫,它提供了對JDK的有用擴展。這裡最重要的流抽象稱為Seq
。請注意,這是一個順序且有序的流,因此調用parallel()
將無效。
4.1。合併流
就像StreamEx庫一樣,jOOλ具有append()
方法:
@Test
public void given2Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> seq1 = Stream.of(1, 3, 5);
Stream<Integer> seq2 = Stream.of(2, 4, 6);
Stream<Integer> resultingSeq = Seq.ofType(seq1, Integer.class)
.append(seq2);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6),
resultingSeq.collect(Collectors.toList()));
}
另外,如果我們將resultingSeq
變量Seq
鍵入為jOOλSeq類型,則toList()
方法也很方便。
4.2。使用prepend()
合併流
不出所料,由於存在append()
方法,因此jOOλ中還有一個prepend()
方法:
@Test
public void given3Streams_whenPrepending_thenResultStreamContainsAllElements() {
Stream<String> seq = Stream.of("foo", "bar");
Stream<String> openingBracketSeq = Stream.of("[");
Stream<String> closingBracketSeq = Stream.of("]");
Stream<String> resultingStream = Seq.ofType(seq, String.class)
.append(closingBracketSeq)
.prepend(openingBracketSeq);
Assert.assertEquals(
Arrays.asList("[", "foo", "bar", "]"),
resultingStream.collect(Collectors.toList()));
}
5.結論
我們看到使用JDK 8合併流是相對簡單的。當需要進行大量合併時,出於可讀性考慮,使用StreamEx或jOOλ庫可能會有所幫助。
您可以在GitHub上找到源代碼。