Java 8: Stream API Stream Operations

Time:2024-2-20

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:mapmapToInt 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 aIntStreami.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📝

Recommended Today

How to understand Context in Go?

Best tutorial I’ve seen so far besides “go language programming”: https://www.practical-go-lessons.com Original text:https://www.practical-go-lessons.com/chap-37-context What will you learn in this chapter? 1. What is context? 2. What is a chained table? 3. How do I use the Context Pack? Technical concepts covered Context derivation Linked list Context key-value pair Cancellation Timeout Deadline present (sb for a […]