What is Stream API in Java ?
Java 8 Stream API Tutorial
- A Steam is a sequence of elements that supports various methods for processing data in parallel or sequentially
- A Stream is not a data structure; it doesn’t store elements.
- Streams can be created from collection, array, or I/O source
- Using Java 8 Stream API You can chain multiple operations together
Key features of Stream API ?
- Supports Functional Programming (Lambda expressions)
- Performs operations like filtering, mapping, and reducing
- Supports parallel processing for better performance
- Does NOT modify the original data (immutable)
- Uses lazy evaluation (processes elements only when needed)
Types of Steams
There are two types of Streams in Java 8.
Sequential Stream: A stream that processes elements one at a time in a sequence.
Parallel Stream: A stream that processes elements concurrently in parallel (e.g., by utilizing multiple CPU cores).
Learn more about other Java 8 features.
How to create a Stream in Java 8
Java 8 Stream API is available in java.util.stream package. There are multiple ways to create streams in Java 8:
From collections (using
stream()
method)From arrays (using
Arrays.stream()
)Using
Stream.of()
for specific valuesFrom files (using
Files.lines()
)Generating infinite streams using
Stream.generate()
andStream.iterate()
Using
parallelStream()
for parallel processing
Creating a Stream using collection
We can create a stream from any collection class (like List, Set, etc.) using the stream() method. Below is an example of creating a stream from a list. Here, we are also using the map function to transform each element of the list to upper case.
//Example: Creating a Stream from a List
import java.util.*;
import java.util.stream.*;
public class StreamExample {
public static void main(String[] args) {
List names = Arrays.asList("Alice", "Bob", "Charlie");
// Creating a stream from a list
Stream nameStream = names.stream();
// Processing: Convert names to uppercase
List uppercaseNames = nameStream.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(uppercaseNames); // [ALICE, BOB, CHARLIE]
}
}
✔ Streams do not modify the original collection
✔ map() applies a transformation to each element
Creating a Stream from an Array
We can create a stream from an array usingArrays.stream() method. example below shows creation of a stream from integer arrays and arrays of objects
//Example: Creating a Stream from integer arrays and arrays of object
import java.util.Arrays;
public class StreamFromArray {
public static void main(String[] args) {
// Creating a stream from an array of primitive type
int[] numbers = {1, 2, 3, 4, 5};
Arrays.stream(numbers)
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // Output: 2, 4
//creating a stream fron array of objects
String[] names = {"John", "Alice", "Bob"};
// Creating a stream from an array of objects
Arrays.stream(names)
.filter(name -> name.length() > 3)
.forEach(System.out::println); // Output: Alice
}
}
Creating a Stream Using Stream.of()
The Stream.of() method creates a stream from a sequence of values.
//Example: Using Stream.of()
import java.util.stream.Stream;
public class StreamFromStreamOf {
public static void main(String[] args) {
// Creating a stream from specific values
Stream namesStream = Stream.of("John", "Alice", "Bob");
namesStream.filter(name -> name.startsWith("J"))
.forEach(System.out::println); // Output: John
}
}
Creating a Stream from a File (I/O Streams)
We can create a stream from a file using Files.lines(), which returns a stream of lines from a file.
//Example: From a File
import java.nio.file.*;
import java.io.IOException;
public class StreamFromFile {
public static void main(String[] args) {
try {
Files.lines(Paths.get("sample.txt"))
.filter(line -> line.contains("Java"))
.forEach(System.out::println); // Output: Lines containing the word "Java"
} catch (IOException e) {
e.printStackTrace();
}
}
}
Creating a Stream Using Stream.generate()
Using Stream.generate() method, we can create an infinite stream by repeatedly applying a provided supplier function
//Example: Generating an Infinite Stream of Random Numbers
import java.util.stream.Stream;
public class StreamGenerate {
public static void main(String[] args) {
// Creating an infinite stream of random numbers
Stream randomNumbers = Stream.generate(Math::random);
// Limiting the stream to the first 5 elements
randomNumbers.limit(5).forEach(System.out::println);
}
}
Creating a Stream Using Stream.iterate()
UsingStream.iterate(),we can create an infinite stream where each element is computed based on the previous one. we can limit the stream to a specific number of elements using limit().
//xample: Iterating Over Numbers
import java.util.stream.Stream;
public class StreamIterate {
public static void main(String[] args) {
// Creating a stream of even numbers starting from 0
Stream evenNumbers = Stream.iterate(0, n -> n + 2);
// Limiting the stream to the first 5 even numbers
evenNumbers.limit(5)
.forEach(System.out::println); // Output: 0, 2, 4, 6, 8
}
}
Creating a Parallel Stream in Java 8
We can create a parallel stream by calling the parallelStream() method on a collection. In Parallel stream each element might be processed in parallel, so we may see different threads processing each element.
//xample: Parallel Stream from a List
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List names = Arrays.asList("John", "Alice", "Bob", "Charlie");
// Creating a parallel stream
names.parallelStream()
.filter(name -> name.length() > 3)
.forEach(name -> System.out.println(Thread.currentThread().getName() + " - " + name));
}
}
Creating an Empty Stream
We can also create an empty stream using empty() method.
Stream emptyStream = Stream.empty();
Java 8 Stream API Operations | Stream API Methods
There are two types of operations are there in Stream API, intermediate operations and terminal operation
- Intermediate Operations: These are operations that transform a stream into another stream. (e.g., filter, map, sorted methods). These methods returns a new object of Stream so that you can chain the multiple operations on a stream which is call as Stream pipeline . They are lazy in nature that means they we be invoked once the terminal operation is called.
- Terminal Operations: These are operations that produce a result or a side effect (e.g., collect, forEach, reduce methods). They terminate the streams so that no further operation is allowed. They are eager and trigger the processing of the stream. Java 8 download.
Intermediate Operations
filter() method
filter() method is used to filter the elements based on some condition. Below is the example to demonstrate how filter works. Here from the list of integers we want to filter even numbers.
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // Output: [2, 4]
map() method
The map() method is used to transform the elements of a stream. In simple words, if we want to perform some operation on the elements of a stream, then we can use a map.
List words = Arrays.asList("apple", "banana", "cherry");
List wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(wordLengths); // Output: [5, 6, 6]
sorted() method
The sorted() method is used to sort the elements of a stream.
List numbers = Arrays.asList(5, 3, 1, 4, 2);
List sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers); // Output: [1, 2, 3, 4, 5]
Terminal Operations
collect() method
collect method is used to collect the elements of a stream into a collection like a List, Set, or Map. This method always returns a new collection.
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List collectedNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(collectedNumbers); // Output: [2, 4]
forEach() method
forEach() method is used to iterate and print the elements of a Stream
List words = Arrays.asList("apple", "banana", "cherry");
words.stream().forEach(System.out::println);
reduce() method
reduce() method reduces the stream to a single value by combining elements.
List numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()reduce(0, (a, b) -> a + b);
System.out.println(sum); // Output: 15
count() method
count() method gives the number of the elements in a stream. It returns a long value.
List words = Arrays.asList("apple", "banana", "cherry");
long count = words.stream()
.filter(word -> word.length() > 5)
.count();
System.out.println(count); // Output: 2
Java 8 Stream API all Methods with examples
Check the official documentation of Java 8 Stream API methods.