Data processing using stream API from Java 8

This blog post shows you how to use ** Java 8 ** to ** Stream API ** to process data declaratively.

In Java, collections and arrays are two common data structures that perform many operations on a regular basis, such as add, delete, modify, query, aggregate, statistics, and filter. These operations also exist in relational databases. However, in Java 8 and earlier, working with collections and arrays is not very convenient.

This issue has been greatly mitigated in Java 8 by introducing a new abstraction called the Stream API, which allows you to process data in a declarative way. This article will show you how to use Stream. Keep in mind that stream performance and principles are not central to this article.

Stream introduction

Streams provide a high-level abstraction of Java collection operations and expressions by querying data from the database, similar to SQL statements.

The Stream API greatly increases the productivity of Java programmers and allows them to write effective, clean and concise code.

The set of elements to process is considered a stream transmitted in the pipeline. These elements can be processed by nodes in the pipeline, such as filters, sorts, and aggregates.

Features and benefits of Java streams

--There is no storage. Streams are just views of the data source, not data structures. --Streams are functional in nature. Changes to the stream do not change the data source. For example, filtering a stream does not remove the filtered elements, but produces a new stream that does not contain the filtered elements. --Lazy evaluation. Operations on the stream are not performed immediately. Only executed when the user really needs the result. --Can be consumed. The elements of the stream are visited only once during the life of the stream. Once traversed, the stream is invalid, like a container iterator. If you want to traverse the Stream again, you need to regenerate the new Stream. Let's use an example to see what Stream can do.

image.png

In the previous example, we take some plastic balls as a data source, filter the red balls and melt them into random triangles. Another filter removes small triangles. The damping agent sums the circumferences.

As shown in the figure above, a stream contains three important operations: stream creation, intermediate operation, and terminal operation.

Stream creation

In Java 8, you can use many methods to create a Stream.

1. Create a stream using an existing collection

In Java 8, in addition to many stream-related classes, the collection class itself has been enhanced. The Java 8 Stream method can convert a collection to a Stream.

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream<String> stream = strings.stream();

In the example above, we are creating a stream from an existing list. The parallelStream method can also create a parallel stream for a collection.

You also often create Streams from collections.

2. Create a stream using the stream method

The of method provided by Stream can be used to directly return a Stream consisting of the specified elements.

Stream<String> stream = Stream.of("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");

The code above uses the of method to create a stream and return it.

Intermediate operation of stream

Streams have many intermediate operations that can be combined to form a pipeline. Each intermediate operation is like a worker on the pipeline. Each worker can process a Stream. The intermediate operation returns a new Stream.

image.png

Below is a list of common intermediate operations.

image.png

filter The filter method is used to filter the elements by the specified criteria. The following code snippet uses the filter method to filter an empty string.

List<String> strings = Arrays.asList("Hollis", "", "HollisChuang", "H", "hollis");
strings.stream().filter(string -> ! string.isEmpty()).forEach(System.out::println);
//Hollis, , HollisChuang, H, hollis

map The map method maps each element to the corresponding result. The code snippet below uses the map method to generate the square number of the corresponding element.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().map( i -> i*i).forEach(System.out::println);
//9,4,4,9,49,9,25

limit/skip Limit returns the first N elements of the Stream. Skip discards the first N elements of Stream. The following code snippet uses the limit method to hold the first four elements.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().limit(4).forEach(System.out::println);
//3,2,2,3

sorted The sorted method sorts the elements of the Stream. The following code snippet uses the sorted method to sort the elements of a Stream.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);
//2,2,3,3,3,5,7

distinct To remove duplicates, use the distinct method. The following code snippet uses the distinct method to deduplication the element.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().distinct().forEach(System.out::println);
//3,2,7,5

Next, I will explain what happens to Stream after performing filter, map, sort, limit, and distinct operations using examples and diagrams.

The code is shown below.

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream s = strings.stream().filter(string -> string.length()<= 6).map(String::length).sorted().limit(3)
            .distinct();

The following figure shows each step and its results.

image.png

Stream terminal business

The terminal operation of the stream also returns Stream. How do I convert a stream to the desired type? For example, count the elements in a Stream and convert that Stream to a collection. Terminal operation is required to do this.

Terminal operations consume Stream and produce the final result. That is, after a terminal operation has been performed on a stream, that stream cannot be reused and no intermediate operations are allowed on that stream. Otherwise an exception will be thrown.

java.lang.IllegalStateException: stream has already been operated upon or closed

This is the same as the saying, "You can't step into the same river twice."

The table below shows common terminal operations.

image.png

forEach The forEach method iterates over the elements in the stream. The following code snippet uses forEach to return 10 random numbers.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

count The count method counts the elements in the Stream.

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis","Hollis666", "Hello", "HelloWorld", "Hollis");
System.out.println(strings.stream().count());
//7

collect A collect operation is a reduce operation that can accept various parameters and accumulate stream elements in the summary result.

List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis","Hollis666", "Hello", "HelloWorld", "Hollis");
strings  = strings.stream().filter(string -> string.startsWith("Hollis")).collect(Collectors.toList());
System.out.println(strings);
//Hollis, HollisChuang, Hollis666, Hollis

Next, we will continue to use filters, maps, sorts, limits, and diagrams showing that separate operations have been performed to show the results of different terminal operations on the Stream given in the above example.

The following figure uses an example to show the inputs and outputs of all the operations described in this article.

image.png

Overview

This article describes how to use streams and their features in Java 8. This article also covers creating streams, intermediate stream operations, and terminal operations.

There are two ways to create a stream, one is to use the stream method of the collection, and the other is to use the stream's of method.

Stream intermediate operations can process streams. Both the input and output of the intermediate operation are Streams. Intermediate operations include filters, maps, and sorts.

Stream intermediate operations can convert a stream to some other container, such as counting the elements in the stream, converting the stream to a collection, or iterating over the elements in the stream.

Recommended Posts

Data processing using stream API from Java 8
[Java] Stream API --Stream termination processing
[Java] Stream API --Stream intermediate processing
I tried using Java8 Stream API
Java Stream API
[Java] Stream processing
Try using the Stream API in Java
[Java] Stream API / map
Java8 Stream API practice
[Java] How to operate List using Stream API
[Java] Generate a narrowed list from multiple lists using the Stream API
Java Stream API cheat sheet
Java Stream API in 5 minutes
Data processing using Apache Flink
[Java] Introduction to Stream API
Using Docker from Java Gradle
[Java] Stream API intermediate operation
[java8] To understand the Stream API
Export issues using JIRA's Java API
[Introduction to Java] About Stream API
Run node.js from android java (processing)
Basic processing flow of java Stream
Call TensorFlow Java API from Scala
Deleting files using recursive processing [Java]
Java 8 ~ Stream API ~ to start now
Sample code using Minio from Java
Sample of using Salesforce's Bulk API from Java client with PK-chunking
[Java] Get data from DB using singleton service in Spring (Boot)
I tried using Elasticsearch API in Java
Call GitHub API from Java Socket API part2
API integration from Java with Jersey Client
Use PostgreSQL data type (jsonb) from Java
Nowadays Java lambda expressions and Stream API
Sort by multiple conditions using Java Stream
Hit the Salesforce REST API from Java
Using JavaScript from Java in Rhino 2021 version
Kinesis Data Streams from zero Java experience (1)
Try using JSON format API in Java
Connect from Java to MySQL using Eclipse
Try various Java Stream API methods (now)
Call Java methods from Nim using jnim
Kinesis Data Streams from zero Java experience (3.1)
Try using the Emotion API from Android
Kinesis Data Streams from zero Java experience (3.2)
Call the Microsoft Emotion API by sending image data directly from Java.
Access Forec.com from Java using Axis2 Enterprise WSDL
Stream API memo
Create API using Retrofit2, Okhttp3 and Gson (Java)
ChatWork4j for using the ChatWork API in Java
[JAVA] Stream type
[Java] API creation using Jerjey (Jax-rs) in eclipse
Try Java 8 Stream
[Java] Get and display the date 10 days later using the Time API added from Java 8.
Try using GCP's Cloud Vision API in Java
Java thread processing
[Processing x Java] Data type and object-oriented programming
Try accessing the dataset from Java using JZOS
Java string processing
Studying Java 8 (Stream)
Java8 Stream duplicate check (write neatly using Collector)
[Java] Multi-thread processing