Stream , Introduced in Java 8, Stream API is mainly used to process collections of objects. A stream in Java is a sequence of objects that supports various operations which can be used to produce the desired result.
Intermediate operations are lazy and return a new stream, allowing for method chaining. Stream processing triggered by terminal operations to produce a result.
Intermediate Operations
Here is a some examples of Java stream intermediate operations:
filter(Predicate):
Filters elements based on a predicate.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(num -> num % 2 == 0)
.collect(Collectors.toList());
// Result: [2, 4]
The filter operation retains only the elements that satisfy the given predicate (in this case, even numbers).
map(Function):
Transforms elements using a function.
Example:
List<String> words = Arrays.asList("hello", "world", "java");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// Result: [5, 5, 4]
The map operation transforms each element by applying the specified function (String::length in this case).
flatMap(Function):
Flattens elements after applying a function.
Example:
List<List<Integer>> numbers = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));
List<Integer> flattenedNumbers = numbers.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// Result: [1, 2, 3, 4]
The flatMap operation flattens nested collections into a single stream of elements.
distinct():
Removes duplicate elements.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
// Result: [1, 2, 3]
The distinct operation eliminates duplicate elements from the stream.
sorted():
Sorts elements.
Example:
List<Integer> numbers = Arrays.asList(3, 1, 2, 4, 5);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
// Result: [1, 2, 3, 4, 5]
The sorted operation arranges the elements in natural order.
peek(Consumer):
Performs an action on each element without affecting the stream.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.stream()
.peek(num -> System.out.println("Processing: " + num))
.count();
// Output: Processing: 1, Processing: 2, Processing: 3
The peek operation allows performing side-effects on elements without modifying the stream.
limit(long):
Limits the number of elements in the stream.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
// Result: [1, 2, 3]
The limit operation restricts the stream to a specified number of elements.
skip(long):
Skips the specified number of elements.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
// Result: [3, 4, 5]
The skip operation bypasses a specified number of elements in the stream.
parallel():
Converts the stream into a parallel stream for concurrent processing.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream()
.forEach(num -> System.out.println(num));
// Output: Order may vary (parallel processing)
The parallel operation enables parallel processing of elements for improved performance.
These are some of the intermediate operations available in Java Streams that facilitate data transformation and manipulation. Each operation serves a specific purpose and can be combined in various ways to achieve complex processing tasks efficiently.
Terminal Operations
Terminal operations in Java Streams are used to produce a final result from the stream. Once a terminal operation is applied, the stream is consumed, and no further intermediate operations can be applied.
Here is a some examples of Java stream terminal operations:
collect(Collectors):
Collects elements from the stream into a collection.
Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String result = names.stream()
.collect(Collectors.joining(", "));
// Result: "Alice, Bob, Charlie"
count():
Returns the count of elements in the stream.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
.count();
// Result: 5
forEach(Consumer):
Performs an action on every element in the stream.
Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.forEach(System.out::println);
// Output: Alice, Bob, Charlie
reduce(BinaryOperator):
Reduces the elements to a single value using a binary operator.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
// Result: 15
min(Comparator) and max(Comparator):
Finds the minimum or maximum element based on a comparator.
Example:
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
Optional<Integer> min = numbers.stream()
.min(Integer::compare);
// Result: 1
anyMatch(Predicate), allMatch(Predicate), and noneMatch(Predicate):
Check if any, all, or no elements match a predicate.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyMatch = numbers.stream()
.anyMatch(num -> num > 3);
// Result: true
findFirst() and findAny():
Returns the first or any element in the stream.
Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> first = names.stream()
.findFirst();
// Result: "Alice"
toArray():
Converts the stream into an array.
Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String[] namesArray = names.stream()
.toArray(String[]::new);
// Result: ["Alice", "Bob", "C
These terminal operations are essential for processing streams and obtaining the desired result. Each operation serves a specific purpose and can be used based on the requirements of the stream processing task.
Conclusion
In this blog, we saw some intermediate operations and terminal operation of Java steams with examples.