GitHub 1.5K Star Java engineers become god’s path, not to learn about it?
GitHub 1.5K Star Java engineers become god’s way, really not to know?
GitHub 1.5K Star Java engineers become god’s way, really sure not to check out?
In Java, collections and arrays are the data structures we often use. They need to be added, deleted, modified, searched, aggregated, counted, filtered and so on. In contrast, these operations are also available in relational databases, but before Java 8, the handling of collections and arrays was not very convenient.
However, this problem has been improved in Java 8, where the API has added a new abstraction called a Stream that lets you process data in a declarative way. This article shows you how to use Stream. In particular, the performance and principle of Stream is not the focus of this article. If you are interested, we will introduce it separately later.
The Stream is introduced
Stream provides a high-level abstraction of Java collection operations and expressions in an intuitive manner similar to querying data from a database with SQL statements.
The Stream API can greatly improve the productivity of Java programmers, allowing programmers to write efficient, clean, and concise code.
This style treats the collection of elements to be processed as a stream that travels through a pipe and can be processed at the nodes of the pipe, such as filtering, sorting, aggregating, and so on.
Stream has the following features and advantages:
- There is no storage. A Stream is not a data structure; it is just a view of some kind of data source, be it an array, a Java container, an I/O channel, etc.
- Designed for functional programming. Any modification to the Stream does not modify the data source behind it. For example, filtering a Stream does not delete the filtered element, but instead produces a new Stream without the filtered element.
- Lazy execution. Operations on Stream are not performed immediately, but only when the user actually needs the result.
- Consumability. A Stream can only be “consumed” once and is invalidated once iterated, just like a container’s iterator, which must be regenerated to iterate again.
Here’s an example of what a Stream can do:
In the example above, take some colored plastic balls and use them as the data source. First filter out the red ones and melt them into random triangles. Filter again and remove small triangles. Finally, the perimeter of the remaining figure is calculated.
As shown in the figure above, there are three key operations for stream processing: stream creation, intermediate operation and terminal operation.
The creation of a Stream
In Java 8, there are several ways to create flows.
1. Create streams from existing collections
In Java 8, in addition to adding many stream-related classes, enhancements have been made to the collection class itself, including the Stream method, which converts a collection class into a Stream.
List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream<String> stream = strings.stream();
Copy the code
Above, create a stream from an existing List. In addition, there is a parallelStream method that creates a parallelStream for collections.
This method of creating a Stream from a collection is also a common one.
Create a Stream through Stream
You can use the methods provided by the Stream class to directly return a Stream consisting of the specified elements.
Stream<String> stream = Stream.of("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Copy the code
Create and return a Stream directly through the of method, as in the above code.
Stream intermediate operation
A Stream has many intermediate operations that can be connected to form an assembly line. Each intermediate operation is like a worker on the assembly line. Each worker can process by convection, and the result after processing is still a flow.
Here is a list of common intermediate actions:
filter
The filter method is used to filter out elements by the set criteria. The following code snippet uses the filter method to filter out empty strings:
List<String> strings = Arrays.asList("Hollis", "", "HollisChuang", "H", "hollis"); strings.stream().filter(string -> ! string.isEmpty()).forEach(System.out::println); //Hollis, , HollisChuang, H, hollisCopy the code
map
The map method is used to map each element to the corresponding result. The following code snippet prints the corresponding square of the element using map:
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,25Copy the code
limit/skip
Limit returns the first n elements of the Stream; Skip is throwing away the first n elements. The following code snippet factoring four elements using the limit method:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().limit(4).forEach(System.out::println); / / 3,2,2,3Copy the code
sorted
The sorted method is used to sort convection. The following code snippet sorts using the sorted method:
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,7Copy the code
distinct
Distinct is mainly used to remove weights. The following code snippet uses distinct to remove weights from elements:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().distinct().forEach(System.out::println); / / 3,2,7,5Copy the code
Let’s use an example and a diagram to show what happens when a Stream is processed by filter, map, sort, limit, and DISTINCT.
The code is as follows:
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();
Copy the code
The process and the results of each step are shown below:
Stream final operation
The intermediate operation on Stream still yields a Stream, so how do we convert a Stream to the desired type? Such as counting the number of elements in the stream, replacing the stream with a collection, and so on. And that requires terminal operation
The final operation consumes the flow, producing an end result. That is, the flow cannot be used again after the final operation, nor can any intermediate operation be used, or an exception will be thrown:
java.lang.IllegalStateException: stream has already been operated upon or closed
Copy the code
That’s what the saying goes, “You never step into the same river twice.”
A common final operation is shown below:
forEach
Stream provides the method ‘forEach’ to iterate over each data in the Stream. The following code snippet prints 10 random numbers using forEach:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
Copy the code
count
Count is used to count the number of elements in the stream.
List<String> strings = Arrays.asList("Hollis", "HollisChuang", "hollis","Hollis666", "Hello", "HelloWorld", "Hollis"); System.out.println(strings.stream().count()); / / 7Copy the code
collect
Collect is a reduction operation that accepts various practices as arguments to accumulate elements in a stream into a 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
Copy the code
Let’s use a diagram to illustrate how a Stream with a filter, map, sort, limit, and DISTINCT operation can result in different results:
The following figure shows the locations, inputs, and outputs of all operations described in this article, and uses a case study to show the results.
conclusion
This article introduces the purpose and benefits of Stream in Java 8. Several uses of Stream are also accepted, namely Stream creation, intermediate action, and final action.
A Stream can be created in two ways: through the Stream method of a collection class and through the of method of a Stream.
An intermediate operation of a Stream can be used to process a Stream. The input and output of an intermediate operation are streams. Intermediate operations can be filtering, converting, sorting, and so on.
The final operation of a Stream can transform the Stream into other forms, such as counting the number of elements in the Stream, loading the Stream into a collection, and traversing the elements.
GitHub 1.5K Star Java engineers become god’s path, not to learn about it?
GitHub 1.5K Star Java engineers become god’s way, really not to know?
GitHub 1.5K Star Java engineers become god’s way, really sure not to check out?