Java 8:Stream API
The Stream API in Java 8 is a set of new features for working with collection data; providing a way to manipulate collections in a declarative style, simplifying the processing of collections, making the code cleaner, more elegant, and able to work with data more efficiently;
This style treats the set of elements to be processed as a stream, which is transported through the pipeline and can be processed at nodes of the pipeline, such as filtering, sorting, aggregating, etc.; the stream of elements is processed in the pipeline through intermediate operation, and finally the result of the previous processing is obtained by the final operation.
+--------------------+ +------+ +------+ +---+ +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+ +------+ +------+ +---+ +-------+
The process is converted to Java code as:
List<Integer> transactionsIds =
widgets.stream()
.filter(b -> b.getColor() == RED)
.sorted((x,y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget::getWeight)
.sum();
characterization
declarative programming style: The Stream API provides a declarative programming approach similar to SQL queries, where data is manipulated by chaining a series of method calls, rather than explicitly writing loops or temporary variables. This makes the code cleaner, more readable and easier to understand.
Inert summation: Stream is inertly evaluated, i.e., it is only actually executed when terminated; intermediate operations (e.g., filter, map, sorted, etc.) only define processing steps for the stream and are not executed immediately; this optimizes processing, avoids unnecessary computation, and improves performance
Functional Interface Support: The Stream API needs to be used with a Functional Interface; a Functional Interface is an interface that contains only one abstract method, and Lambda expressions can be passed as instances of the Functional Interface; this support allows the Stream API to take full advantage of functional programming
generating stream
In Java 8, the collection interface has two methods for generating streams
stream()
: Create serial streams for collections
parallelStream()
-:Create parallel streams for collections
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
The list of strings creates a stream, which is converted into a stream by the stream() method; then, the filter method is used to pass a Lambda expression to sift (filter) the elements that don’t satisfy the condition; in this case, the Lambda expression string -> !string.isEmpty() checks to see if the string is non-null; Only if the string is not empty, the element is kept in the stream; finally, the collect method, in conjunction with the Collectors.toList() collector, is used to collect the elements that meet the conditions into a new list, filtered
streaming operation
forEach
Stream provides new methodsforEach
to iterate over each piece of data in the stream: the following code snippet outputs 10 random numbers using forEach:
ints()
method is used to generate an infinite stream of random integers
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
map
The map method is used to map each element to its corresponding result: the following code snippet outputs the square number of the corresponding element using map
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// Get the corresponding square number
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filter
The filter method is used to filter out elements by a set condition: the following code snippet uses the filter method to filter out empty strings
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// Get the number of empty strings
long count = strings.stream().filter(string -> string.isEmpty()).count();
limit
The limit method is used to get a specified number of streams: the following code snippet prints out 10 pieces of data using the limit method
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
sorted
The sorted method is used to sort the stream: the following code snippet uses the sorted method to sort the output of 10 random numbers
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
parallel (parallel) program
parallelStream is an alternative to stream parallelizers: in the following example we use parallelStream to output the number of empty strings
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// Get the number of empty strings
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
Collectors
The Collectors class implements a number of reductive operations, such as converting streams into collections and aggregated elements: Collectors can be used to return lists or strings
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println(" Filter list: "+ filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
statisticians
Collectors that produce statistics; they are mainly used on basic types such as int, double, long, etc. They can be used to produce statistics like the following
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Largest number in list : " + stats.getMax());
System.out.println("Smallest number in list : " + stats.getMin());
System.out.println("Sum of all counts : " + stats.getSum());
System.out.println(" average: "+ stats.getAverage());
map operation
Three common map operations in the Stream API:map
、mapToInt
respond in singingflatMap
map
: Used to map elements in a stream to another type of stream. For example, mapping each object in an object stream to a stream consisting of the values of one of the object’s attributes
mapToInt
: Used to map elements in a stream to aIntStream
i.e., basic typesint
of the stream. It is typically used to map elements in a stream to integer values
flatMap
: Used to map each element in a stream to a stream and then join those streams into a single stream. It is often used to flatten the processing of nested stream structures
case (law)
systemApplicationTypeRepo.list(new QueryWrapper<SystemApplicationType>().orderByAsc(SystemApplicationTypeCol.ID))
.stream().map(bean -> new ResCommonIdNameCode(bean.getId(), bean.getName(), bean.getName())).collect(Collectors.toList()
systemApplicationTypeRepo.list(...)
: This part of the code uses a repository called systemApplicationTypeRepo to query the database by calling the list method, which accepts a QueryWrapper as a parameter that specifies the query conditions.
new QueryWrapper<SystemApplicationType>().orderByAsc(SystemApplicationTypeCol.ID)
This is the process of creating a query condition object; QueryWrapper is a tool provided by MyBatis-Plus for constructing query conditions; orderByAsc(SystemApplicationTypeCol.ID) indicates that the query conditions are sorted according to the ascending order of the ID field of the SystemApplicationType entity class. ID field in the SystemApplicationType entity class.
.stream()
: This converts the query result into a Stream object for subsequent operations.
.map(bean -> new ResCommonIdNameCode(bean.getId(), bean.getName(), bean.getName()))
: This section uses the map operation to map each SystemApplicationType object in the query result to a ResCommonIdNameCode object; ResCommonIdNameCode is a customized class with a constructor that accepts id, name, and code as arguments to create a new object.
.collect(Collectors.toList())
: Finally, use the collect method to collect the Stream objects into a List, the final list of results.
noticeResponses.stream()
.sorted(Comparator.comparing(SystemNoticeResponse::getReadStatus)
.thenComparing(Comparator.comparing(SystemNoticeResponse::getCreateAt).reversed()))
.collect(Collectors.toList());
.stream()
: Converts a list of noticeResponses into a Stream object, enabling it to use the operations provided by the Stream API
.sorted(...)
: this is an intermediate operation to sort the elements in the stream; use Comparator.comparing(…) method to create a comparator to specify the rules of sorting; first, sort by the readStatus field of the SystemNoticeResponse object in ascending order; . thenComparing(…) means that if the readStatus is the same, then sort in descending order by the createAt field (using the reversed() method)
.collect(Collectors.toList())
: Finally, use the collect method to collect the sorted Stream objects into a new List, the sorted list of noticeResponses.
Conclusion: it’s not easy to create, if you find the blogger’s article pleasing to the eye, please also –pointing and calling (e.g. camera)
👍favorite
⭐️commentaries
📝