GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing zetcode.com — Java Stream - processing data in Java with streams Java StreamLast modified May 23, 2025 This article explores how Java Streams enable efficient data processing. You will learn how to create streams from various sources and apply essential operations to improve performance and readability in Java programs. Java stream definitionStream is a sequence of elements from a source that supports sequential and parallel aggregate operations. Common aggregate operations include filter, map, reduce, find, match, and sort. The source can be a collection, IO operation, or array, which provides data to the stream.
A Java collection is an in-memory data structure containing all elements, while
a stream computes elements on demand. Unlike collections, which require explicit
(external) iteration, streams handle iteration internally. Since Java 8,
collections have a
The Stream operations produce results without modifying their source. Characteristics of a stream
Stream pipelineA stream pipeline consists of a source, intermediate operations, and a terminal operation. Intermediate operations return a new, modified stream, allowing you to chain multiple operations. Terminal operations return a value or void. After a terminal operation, the stream cannot be used further. Short-circuiting a terminal operation means the stream may terminate before processing all values, which is useful for infinite streams. Intermediate operations are lazy; they are not invoked until a terminal operation is executed. This improves performance when processing large data streams. Creating streamsStreams can be created from collections, arrays, strings, IO resources, or generators. Main.java
void main() {
List<String> words = List.of("pen", "coin", "desk", "chair");
String word = words.stream().findFirst().get();
System.out.println(word);
Stream<String> letters = Arrays.stream(new String[]{"a", "b", "c"});
System.out.printf("There are %d letters%n", letters.count());
String day = "Sunday";
IntStream istr = day.codePoints();
String s = istr.filter(e -> e != 'n').collect(StringBuilder::new,
StringBuilder::appendCodePoint, StringBuilder::append).toString();
System.out.println(s);
}
This example demonstrates working with streams created from a list, an array, and a string. List<String> words = List.of("pen", "coin", "desk", "chair");
A list of strings is created. String word = words.stream().findFirst().get();
We use the Stream<String> letters = Arrays.stream(new String[]{ "a", "b", "c"});
System.out.printf("There are %d letters%n", letters.count());
We create a stream from an array. The String day = "Sunday";
IntStream istr = day.codePoints();
String s = istr.filter(e -> e != 'n').collect(StringBuilder::new,
StringBuilder::appendCodePoint, StringBuilder::append).toString();
System.out.println(s);
Here, we create a stream from a string, filter its characters, and build a new string from the filtered characters. $ java Main.java pen There are 3 letters Suday
There are three Main.java
void main() {
IntStream integers = IntStream.rangeClosed(1, 16);
var res = integers.average();
if (res.isPresent()) {
System.out.println(res.getAsDouble());
}
DoubleStream doubles = DoubleStream.of(2.3, 33.1, 45.3);
doubles.forEachOrdered(System.out::println);
LongStream longs = LongStream.range(6, 25);
System.out.println(longs.count());
}
This example demonstrates the use of the three stream specializations. IntStream integers = IntStream.rangeClosed(1, 16); System.out.println(integers.average().getAsDouble());
A stream of integers is created with the if (res.isPresent()) {
System.out.println(res.getAsDouble());
}
If the value is present, we print the average to the console. DoubleStream doubles = DoubleStream.of(2.3, 33.1, 45.3); doubles.forEachOrdered(System.out::println);
A stream of double values is created with the LongStream longs = LongStream.range(6, 25); System.out.println(longs.count());
A stream of long integers is created with the $ java Main.java 8.5 2.3 33.1 45.3 19
The Main.java
void main() {
Stream<String> colours = Stream.of("red", "green", "blue");
Optional<String> col = colours.skip(2).findFirst();
col.ifPresent(System.out::println);
Stream<Integer> nums = Stream.of(3, 4, 5, 6, 7);
Optional<Integer> maxVal = nums.max(Comparator.naturalOrder());
maxVal.ifPresent(System.out::println);
}
This example shows how to use Stream<String> colours = Stream.of("red", "green", "blue");
A stream of three strings is created. Optional<String> col = colours.skip(2).findFirst();
Using the col.ifPresent(System.out::println); We print the value if it is present. Stream<Integer> nums = Stream.of(3, 4, 5, 6, 7); Optional<Integer> maxVal = nums.max(Comparator.naturalOrder()); maxVal.ifPresent(System.out::println); We create a stream of integers and find its maximum value. $ java Main.java blue 7
Other ways to create streams include Main.java
void main() {
Stream<Integer> s1 = Stream.iterate(5, n -> n * 2).limit(10);
s1.forEach(System.out::println);
Stream.generate(new Random()::nextDouble)
.map(e -> (e * 10))
.limit(5)
.forEach(System.out::println);
}
This example creates two streams using Stream<Integer> s1 = Stream.iterate(5, n -> n * 2).limit(10); s1.forEach(System.out::println);
The Stream.generate(new Random()::nextDouble)
.map(e -> (e * 10))
.limit(5)
.forEach(System.out::println);
A stream of five random doubles is created with $ java Main.java 5 10 20 40 80 160 320 640 1280 2560 8.704675577530493 5.732011478196306 3.8978402578067515 3.6986033299500933 6.0976417139147205 You can also create a stream from a file. Main.java
void main() throws IOException {
Path path = Paths.get("/home/janbodnar/myfile.txt");
try (Stream<String> stream = Files.lines(path)) {
stream.forEach(System.out::println);
}
}
This example reads a file and prints its contents using streams. Path path = Paths.get("/home/janbodnar/myfile.txt");
A try (Stream<String> stream = Files.lines(path)) {
...
}
From the path, we create a stream using stream.forEach(System.out::println); We iterate through the stream and print each line to the console. Internal and external iterationDepending on who controls the iteration process, we distinguish between external and internal iteration. External iteration, also known as explicit iteration, is handled by the programmer and was the only type available before Java 8. For external iteration, we use for and while loops. Internal iteration, also called implicit iteration, is controlled by the iterator itself and is available in Java streams. Main.java
void main() {
var words = List.of("pen", "coin", "desk", "eye", "bottle");
Iterator<String> it = words.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
In this code example, we retrieve an iterator from a list of strings. Using the
iterator's In the following example, we iterate over the same list using internal iteration. Main.java
void main() {
var words = List.of("pen", "coin", "desk", "eye", "bottle");
words.stream().forEach(System.out::println);
}
Here, we create a stream from a list and use the stream's words.stream().forEach(System.out::println);
This can be shortened to Stream filtering
Filtering data is one of the most important features of streams. The
Main.java
void main() {
IntStream nums = IntStream.rangeClosed(0, 25);
int[] vals = nums.filter(e -> e > 15).toArray();
System.out.println(Arrays.toString(vals));
}
This code example creates a stream of integers and filters it to contain only values greater than fifteen. IntStream nums = IntStream.rangeClosed(0, 25);
With int[] vals = nums.filter(e -> e > 15).toArray();
We pass a lambda expression ( System.out.println(Arrays.toString(vals)); The array is printed to the console. $ java Main.java [16, 17, 18, 19, 20, 21, 22, 23, 24, 25] The next example produces a list of even numbers. Main.java
void main() {
IntStream nums = IntStream.rangeClosed(0, 30);
nums.filter(this::isEven).forEach(System.out::println);
}
boolean isEven(int e) {
return e % 2 == 0;
}
To get even numbers from a stream, we pass an nums.filter(this::isEven).forEach(System.out::println);
The double colon (::) operator is used to pass a method reference. The
Skipping and limiting elements
The Main.java
void main() {
IntStream s = IntStream.range(0, 15);
s.skip(3).limit(5).forEach(System.out::println);
}
This example creates a stream of fifteen integers, skips the first three
elements with $ java Main.java 3 4 5 6 7 Sorting elements
The Main.java
void main() {
IntStream nums = IntStream.of(4, 3, 2, 1, 8, 6, 7, 5);
int[] sorted = nums.sorted().toArray();
System.out.println("Sorted: " + Arrays.toString(sorted));
}
This example sorts integer elements in descending order. The $ java Main.java 8 7 6 5 4 3 2 1 The next example shows how to sort a stream of objects. Main.java
record Car(String name, int price) {
}
void main() {
List<Car> cars = List.of(new Car("Citroen", 23000),
new Car("Porsche", 65000), new Car("Skoda", 18000),
new Car("Volkswagen", 33000), new Car("Volvo", 47000));
cars.stream().sorted(Comparator.comparing(Car::price))
.forEach(System.out::println);
}
The example sorts cars by their price. List<Car> cars = List.of(new Car("Citroen", 23000),
new Car("Porsche", 65000), new Car("Skoda", 18000),
new Car("Volkswagen", 33000), new Car("Volvo", 47000));
A list of cars is created. cars.stream().sorted(Comparator.comparing(Car::price))
.forEach(System.out::println);
A stream is generated from the list using the $ java Main.java
Car{name=Skoda, price=18000}
Car{name=Citroen, price=23000}
Car{name=Volkswagen, price=33000}
Car{name=Volvo, price=47000}
Car{name=Porsche, price=65000}
Unique values
The Main.java
void main() {
IntStream nums = IntStream.of(1, 1, 3, 4, 4, 6, 7, 7);
int[] a = nums.distinct().toArray();
System.out.println(Arrays.toString(a));
}
This example removes duplicate values from a stream of integers. IntStream nums = IntStream.of(1, 1, 3, 4, 4, 6, 7, 7); There are three duplicate values in the stream. int[] a = nums.distinct().toArray();
We remove the duplicates with the $ java Main.java [1, 3, 4, 6, 7] Mapping operations
It is possible to transform elements into a new stream; the original source is
not modified. The Main.java
void main() {
IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8);
int[] squares = nums.map(e -> e * e).toArray();
System.out.println(Arrays.toString(squares));
}
We map a transformation function onto each element of the stream. int[] squares = nums.map(e -> e * e).toArray();
We apply a lambda expression ( $ java Main.java [1, 4, 9, 16, 25, 36, 49, 64] In the next example, we transform a stream of strings. Main.java
void main() {
Stream<String> words = Stream.of("cardinal", "pen", "coin", "globe");
words.map(this::capitalize).forEach(System.out::println);
}
String capitalize(String word) {
word = word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
return word;
}
We have a stream of strings and capitalize each string in the stream. words.map(this::capitalize).forEach(System.out::println);
We pass a reference to the $ java Main.java Cardinal Pen Coin Globe Stream reductionsA reduction is a terminal operation that aggregates a stream into a single value or primitive. Main.java
void main() {
IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8);
OptionalInt maxValue = nums.max();
if (maxValue.isPresent()) {
System.out.printf("The maximum value is: %d%n", maxValue.getAsInt());
}
}
This example demonstrates a reduction operation that finds the maximum value in a stream of integers. OptionalInt maxValue = nums.max();
With the if (maxValue.isPresent()) {
System.out.printf("The maximum value is: %d%n", maxValue.getAsInt());
}
We print the value if it is present. $ java Main.java The maximum value is: 8
A custom reduction can be created with the Main.java
void main() {
IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8);
OptionalInt product = nums.reduce((a, b) -> a * b);
if (product.isPresent()) {
System.out.printf("The product is: %d%n", product.getAsInt());
}
}
This example returns the product of the integer elements in the stream. $ java Main.java The product is: 40320 Collection operationsA collection is a terminal reduction operation that reduces elements of a stream into a Java collection, string, value, or specific grouping. Main.java
record Car(String name, int price) {
}
void main() {
List<Car> cars = List.of(new Car("Citroen", 23000),
new Car("Porsche", 65000), new Car("Skoda", 18000),
new Car("Volkswagen", 33000), new Car("Volvo", 47000));
List<String> names = cars.stream().map(Car::name)
.filter(name -> name.startsWith("Vo"))
.collect(Collectors.toList());
for (String name : names) {
System.out.println(name);
}
}
This example creates a stream from a list of car objects, filters the cars by their name, and returns a list of matching car names. List<String> names = cars.stream().map(Car::name)
.filter(name -> name.startsWith("Vo"))
.collect(Collectors.toList());
At the end of the pipeline, we use the $ java Main.java Volkswagen Volvo
In the next example, we use the Main.java
void main() {
List<String> items = List.of("pen", "book", "pen", "coin",
"book", "desk", "book", "pen", "book", "coin");
Map<String, Long> result = items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
for (Map.Entry<String, Long> entry : result.entrySet()) {
String key = entry.getKey();
Long value = entry.getValue();
System.out.format("%s: %d%n", key, value);
}
}
This code example groups elements by their occurrence in a stream. Map<String, Long> result = items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
With the for (Map.Entry<String, Long> entry : result.entrySet()) {
String key = entry.getKey();
Long value = entry.getValue();
System.out.format("%s: %d%n", key, value);
}
We iterate through the map and print its key/value pairs. $ java Main.java desk: 1 book: 4 pen: 3 coin: 2 Source
In this article we have learned how to create and use Java streams. We have
seen how to create streams from collections, arrays, strings, and IO
resources. We have also learned how to filter, sort, and map streams.
We have learned how to perform reductions and collect results into
Java collections. We have also learned how to use the AuthorMy name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming. List all Java tutorials. |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |