Java 8
Streams
Java Programming
Stream Manipulation
Functional Programming

Adding two Java 8 streams, or an extra element to a stream

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Java 8 introduced the Stream API, a powerful tool for processing sequences of elements. Streams in Java allow developers to perform complex data manipulation with ease using a mix of declarative and functional programming styles. However, Streams are immutable: any transformation results in a new stream while leaving the original one unaffected. This article explores how to merge two streams or add an additional element to a stream, emphasizing both technical intricacies and practical examples.

Combining Two Streams

Combining two streams in Java 8 can be achieved using the Stream.concat() method. This method creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.

Example

java
1import java.util.stream.Stream;
2
3public class StreamExample {
4    public static void main(String[] args) {
5        Stream<String> stream1 = Stream.of("Apple", "Banana", "Cherry");
6        Stream<String> stream2 = Stream.of("Dates", "Elderberry", "Fig");
7
8        Stream<String> combinedStream = Stream.concat(stream1, stream2);
9
10        combinedStream.forEach(System.out::println);
11    }
12}

Technical Explanation

  • Lazy Evaluation: The Stream.concat() method constructs a new stream that will yield the results of the concatenation lazily when its operations are executed.
  • Terminal Operations: The combined stream above will not output any elements until a terminal operation, such as forEach(), is invoked.

Adding an Element to a Stream

Streams themselves do not directly support adding an element. However, you can achieve this by first combining your stream with another single-element stream.

Example

java
1import java.util.stream.Stream;
2
3public class AddElementToStream {
4    public static void main(String[] args) {
5        Stream<String> originalStream = Stream.of("Lemon", "Lime");
6
7        // Adding an element "Mango"
8        Stream<String> modifiedStream = Stream.concat(originalStream, Stream.of("Mango"));
9
10        modifiedStream.forEach(System.out::println);
11    }
12}

Technical Explanation

  • Immutability: Streams are immutable and do not support direct modification. Therefore, to add elements, we use Stream.concat() to produce a new stream containing both the original elements and the additional ones.
  • Single-Element Stream: The use of Stream.of() is crucial because it transforms a single item into a stream, allowing it to be concatenated.

Using Collectors for Combining

In scenarios where working with collections is preferable, the Collectors class offers another approach to combine elements efficiently.

Example

java
1import java.util.List;
2import java.util.stream.Collectors;
3import java.util.stream.Stream;
4
5public class CollectorsExample {
6    public static void main(String[] args) {
7        List<String> list1 = Stream.of("Grape", "Guava").collect(Collectors.toList());
8        List<String> list2 = Stream.of("Kiwi").collect(Collectors.toList());
9
10        list1.addAll(list2);
11
12        list1.forEach(System.out::println);
13    }
14}

Technical Explanation

  • Mutable Collection: Convert streams to mutable collections such as List using Collectors.toList(), which allows additions using standard collection operations.
  • Efficiency Considerations: Working with collections might be required if altering collection data is crucial. However, it detracts from the functional paradigm of stream operations.

Summary Table

Below is a table summarizing key aspects of handling Java 8 streams:

AspectMethod/ApplicationDescription
Merging Two StreamsStream.concat()Combines two streams into one. Lazy evaluation.
Adding Element to StreamStream.concat()Cannot modify directly, concatenate a single-item stream.
Converting to ListCollectors.toList()Convert streams to list for mutability.
Operations TriggeringLazy execution via terminal operationsNo operations executed without a terminal operation.

Conclusion

Handling streams effectively requires an understanding of their immutable nature and the lazy evaluation model. Java 8 provides flexible means to merge streams or add elements, either by utilizing Stream.concat() or converting them to collections for further manipulation. Choose the approach that best aligns with your programming goals and embrace the functional paradigm that streams offer for streamlined data processing.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions