1. Обзор
В этой краткой статье мы объясним различные способы объединения Java Streams , что не очень интуитивно понятно.
2. Использование простой Java
Класс JDK 8 Stream имеет некоторые полезные статические служебные методы. Давайте подробнее рассмотрим метод concat () .
2.1. Слияние Двух Потоков
Самый простой способ объединить 2 Stream s-использовать статический метод Stream.concat() :
@Test public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() { Streamstream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream resultingStream = Stream.concat(stream1, stream2); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6), resultingStream.collect(Collectors.toList())); }
2.2. Объединение Нескольких Потоков
Когда нам нужно объединить более 2 потоков, все становится немного сложнее. Одна из возможностей состоит в том, чтобы объединить первые два потока, затем объединить результат со следующим и так далее.
Следующий фрагмент кода показывает это в действии:
@Test public void given3Streams_whenMerged_thenResultStreamContainsAllElements() { Streamstream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream 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() { Streamstream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream stream4 = Stream.of(99); Stream 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 Потока, в результате чего получается Поток<Поток<Целое число>>
- Затем мы flatMap() преобразуем это в Поток<Целое число> с помощью функции идентификации
3. Использование Streamyx
Stream Ex -это библиотека Java с открытым исходным кодом, которая расширяет возможности потоков Java 8. Он использует класс StreamEx в качестве улучшения интерфейса Stream JDK.
3.1. Слияние потоков
Библиотека StreamEx позволяет объединять потоки с помощью метода append() instance:
@Test public void given4Streams_whenMerged_thenResultStreamContainsAllElements() { Streamstream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream stream4 = Stream.of(99); Stream 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())); }
Поскольку это метод экземпляра, мы можем легко связать его в цепочку и добавить несколько потоков.
Обратите внимание, что мы также можем создать Список из потока с помощью ToList () , если мы введем переменную результирующего потока в тип StreamEx .
3.2. Объединение Потоков С Помощью prepend()
Streamyx также содержит метод, который добавляет элементы друг перед другом под названием prepend() :
@Test public void given3Streams_whenPrepended_thenResultStreamContainsAllElements() { Streamstream1 = Stream.of("foo", "bar"); Stream openingBracketStream = Stream.of("["); Stream closingBracketStream = Stream.of("]"); Stream 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, Joopl имеет метод append() :
@Test public void given2Streams_whenMerged_thenResultStreamContainsAllElements() { Streamseq1 = Stream.of(1, 3, 5); Stream seq2 = Stream.of(2, 4, 6); Stream resultingSeq = Seq.ofType(seq1, Integer.class) .append(seq2); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6), resultingSeq.collect(Collectors.toList())); }
Кроме того, существует удобный метод ToList () , если мы введем переменную resultingSeq в тип jOOλ Seq .
4.2. Объединение Потоков С добавлением()
Как и ожидалось, поскольку существует метод append () , в JOOPL также есть метод prepend() :
@Test public void given3Streams_whenPrepending_thenResultStreamContainsAllElements() { Streamseq = Stream.of("foo", "bar"); Stream openingBracketSeq = Stream.of("["); Stream closingBracketSeq = Stream.of("]"); Stream resultingStream = Seq.ofType(seq, String.class) .append(closingBracketSeq) .prepend(openingBracketSeq); Assert.assertEquals( Arrays.asList("[", "foo", "bar", "]"), resultingStream.collect(Collectors.toList())); }
5. Заключение
Мы видели, что объединение потоков относительно просто с помощью JDK 8. Когда нам нужно сделать много слияний, может быть полезно использовать библиотеку StreamEx или Joopl для удобства чтения.
Вы можете найти исходный код на GitHub .