“This is the 21st day of my participation in the Gwen Challenge in November. See details of the event: The Last Gwen Challenge 2021”.
preface
Hello everyone, I’m Llamy. Streaming computing has always been a problem that appears frequently in Java interview. Today’s “Interview God” series will talk about the implementation of Java stream merge.
Plain Java methods
The JDK 8 Stream class has some useful static methods. Such as concat () :
Merge two streams
@Test
public void merge(a) {
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()));
}
Copy the code
Merging multiple streams
When we merge multiple streams, things get a little more complicated. One possible approach is to merge the first two flows and then use the merge result to merge the other flows.
Such as:
@Test
public void merge(a) {
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()));
}
Copy the code
This method is not feasible for more rheologies. Of course, we could create intermediate variables or helper methods to make it more readable, but there is a better way:
@Test
public void merge(a) {
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()));
}
Copy the code
It goes through two steps:
- Start by creating a new Stream with four Streams and generate a nested Stream
- And then we use the identity function
flatMap()
Into the Stream
Using StreamEx
StreamEx is an open source Java library that extends the possibilities of Java 8 Streams. It uses the StreamEx class as an enhancement to the Stream interface of the JDK.
Combined flow
The StreamEx library allows us to merge streams using the append() instance method:
@Test
public void merge(a) {
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()));
}
Copy the code
Because it is an instance method, we can easily link it together and attach multiple Streams.
Use prepend() to merge streams
StreamEx also contains a method that adds an element before another, called prepend() :
@Test
public void merge(a) {
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()));
}
Copy the code
Using Joo lambda.
Joo λ is a JDK 8 compatible library that provides useful extensions to the JDK. The most important flow abstraction here is called SEQ. Note that this is a sequential and ordered stream, so calling parallel() will have no effect.
Combined flow
Like the StreamEx library, jooλ has an append() method:
@Test
public void merge(a) {
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()));
}
Copy the code
Use prepend() to merge streams
@Test
public void merge(a) {
Stream<String> seq = Stream.of("foo"."bar");
Stream<String> openingBracketStream = Stream.of("[");
Stream<String> closingBracketStream = Stream.of("]");
Stream<String> resultingStream = Seq.ofType(seq, String.class)
.append(closingBracketStream)
.prepend(openingBracketStream);
assertEquals(
Arrays.asList("["."foo"."bar"."]"),
resultingStream.collect(Collectors.toList()));
}
Copy the code
conclusion
It’s easy to merge two streams using JDK 8, but when we need to merge multiple streams using SteamEx or the JOOλ library we can append streams by append(), which is much more readable.