Ten thousand words of detailed explanation of Stream and Lambda (just read this article)

What is Stream?

Stream is a new way of processing collection data in Java 8. It provides a streaming processing method similar to database operations. It can filter, map, sort, aggregate and other operations on collections, making collection operations more efficient. Simple and efficient.

Stream stream mainly has the following characteristics:

  • Stream is not a data structure and does not change the source data. Instead, it generates a new data stream by operating on the source data.
  • Stream supports chain operations and can combine multiple operations, making the code more concise.
  • Stream stream supports delayed operation, and calculation will only be performed when the operation is terminated, which can improve the performance of the program.
  • Stream can perform parallel operations and take advantage of the performance advantages of multi-core processors to improve the calculation speed of the program.

How to use Stream?

Using Stream can be divided into the following steps:

  1. Obtain data sources: Data sources can be obtained through collections, arrays, IO streams, etc.
  2. Convert to stream: Convert the data source to a stream through methods such as stream() and parallelStream().
  3. Intermediate operations: Perform intermediate operations on the stream, such as filtering, mapping, sorting, deduplication, etc. These operations will return a new stream.
  4. Termination operation: perform termination operations on the stream, such as collection, counting, search, matching, etc. These operations will return a result.

The methods and usage examples of each operation will be introduced below.

1. Get the data source

Data sources can be obtained through collections, arrays, IO streams, etc.

Get a data source using a collection

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");

Get data source using array

String[] array = {
    
    "apple", "banana", "orange", "grape", "watermelon"};

2. Convert to stream

Convert the data source into a stream through methods such as stream() and parallelStream().

Convert collection to stream

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Stream<String> stream = list.stream();

Convert array to stream

String[] array = {
    
    "apple", "banana", "orange", "grape", "watermelon"};
Stream<String> stream = Arrays.stream(array);

3. Intermediate operations

Perform intermediate operations on the stream, such as filtering, mapping, sorting, deduplication, etc. These operations will return a new stream.

Filter data

Filter out strings whose length is less than or equal to 5:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Stream<String> stream = list.stream().filter(str -> str.length() > 5);

Mapping data

Extract the names of all fruits:

List<Fruit> fruits = Arrays.asList(
    new Fruit("apple", "red"),
    new Fruit("banana", "yellow"),
    new Fruit("orange", "orange"),
    new Fruit("grape", "purple"),
    new Fruit("watermelon", "green")
);
Stream<String> stream = fruits.stream().map(Fruit::getName);

Sort data

Sort by fruit name:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Stream<String> stream = list.stream().sorted();

Deduplicate data

Remove duplicate fruit names:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon", "apple", "banana");
Stream<String> stream = list.stream().distinct();

4. Terminate operation

Perform termination operations on the stream, such as collection, counting, search, matching, etc., these operations will return a result.

Data collection

Collect fruit names into a list:

List<Fruit> fruits = Arrays.asList(
    new Fruit("apple", "red"),
    new Fruit("banana", "yellow"),
    new Fruit("orange", "orange"),
    new Fruit("grape", "purple"),
    new Fruit("watermelon", "green")
);
List<String> names = fruits.stream().map(Fruit::getName).collect(Collectors.toList());

count data

Count the number of fruit names:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon", "apple", "banana");
long count = list.stream().count();

Find data

Find the first fruit name:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Optional<String> first = list.stream().findFirst();

Match data

Determine whether a certain fruit name is included:

List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
boolean contains = list.stream().anyMatch(str -> str.equals("banana"));

How to use Lambda expressions?

Lambda expressions can be used in functional interfaces, which are interfaces that contain only one abstract method.

Basic syntax of lambda expressions:

(parameters) -> expression

Among them, parameters is the parameter list of the method, and expression is the method body.

Examples of using Lambda expressions are introduced below.

1. Use Lambda expressions as parameters

Pass a Lambda expression as a parameter to another method:

public void process(int num, IntConsumer consumer) {
    
    
    consumer.accept(num);
}

public static void main(String[] args) {
    
    
    LambdaExample example = new LambdaExample();

    // 使用Lambda表达式作为参数
    example.process(10, (num) -> System.out.println(num));

    // 使用Lambda表达式实现函数接口
    Function<Integer, Integer> square = (num) -> num * num;
    int result = square.apply(5);
    System.out.println(result);

    // 使用Lambda表达式简化集合操作
    List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");

    // 使用Lambda表达式实现筛选
    List<String> filteredList = list.stream().filter(str -> str.length() > 5).collect(Collectors.toList());

    // 使用Lambda表达式实现映射
    List<String> mappedList = list.stream().map(str -> str.toUpperCase()).collect(Collectors.toList());

    // 使用Lambda表达式实现排序
    List<String> sortedList = list.stream().sorted().collect(Collectors.toList());

    // 使用Lambda表达式实现去重
    List<String> distinctList = list.stream().distinct().collect(Collectors.toList());
}

2. Use Lambda expressions to implement functional interfaces

Use Lambda expressions to implement a functional interface:

Function<Integer, Integer> square = (num) -> num * num;

3. Use Lambda expressions to simplify set operations

Lambda expressions can simplify collection operations, such as filtering, mapping, sorting, deduplication, etc. Here are some common examples of collection operations:

3.1 Filtering operation

Filtering operations can be implemented through the filter method, which can filter elements in the collection based on conditions and return a new Stream. For example, here is an example of a filter operation:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = numbers.stream()
                                    .filter(n -> n % 2 == 0)
                                    .collect(Collectors.toList());
System.out.println(evenNumbers); // [2, 4, 6, 8, 10]

In this example, first create a List collection containing integers 1 to 10, then use the filter method of the Stream stream to filter out the even numbers, and save the result to a new List collection.

3.2 Mapping operation

Mapping operations can be implemented through the map method, which maps an element in a collection to another element and returns a new Stream. For example, here is an example of a mapping operation:

List<String> words = Arrays.asList("hello", "world", "java", "stream", "lambda");
List<Integer> lengths = words.stream()
                                .map(String::length)
                                .collect(Collectors.toList());
System.out.println(lengths); // [5, 5, 4, 6, 6]

In this example, you first create a List collection containing strings, then use the map method of the Stream stream to map each string to its length, and save the result to a new List collection.

3.3 Sorting operation

Sorting operations can be implemented through the sorted method, which sorts the elements in the collection and returns a new Stream. For example, here is an example of a sort operation:

List<String> words = Arrays.asList("hello", "world", "java", "stream", "lambda");
List<String> sortedWords = words.stream()
                                    .sorted()
                                    .collect(Collectors.toList());
System.out.println(sortedWords); // [hello, java, lambda, stream, world]

In this example, first create a List collection containing strings, then use the sorted method of the Stream stream to sort the strings, and save the results to a new List collection.

3.4 Deduplication operation

The deduplication operation can be implemented through the distinct method, which can remove duplicate elements from the collection and return a new Stream. For example, here is an example of a deduplication operation:

List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 5, 4, 6, 7, 5);
List<Integer> distinctNumbers = numbers.stream()
                                            .distinct()
                                            .collect(Collectors.toList());
System.out.println(distinctNumbers); // [1, 2, 3, 4

Usage scenarios of Lambda expressions
Lambda expressions are suitable for handling the following scenarios:

  • Functional interface: Lambda expressions can be used as implementations of functional interfaces. A functional interface contains only an abstract method, which can be implemented using Lambda expressions.
  • Collection operations: Streams can be used to process elements in collections, such as filtering, mapping, sorting, deduplication, etc. Lambda expressions can be used to simplify the code.
  • Multi-threaded programming: Lambda expressions can be used as implementations of Runnable and Callable interfaces, making multi-threaded programming more convenient.
  • GUI event listener: Lambda expressions can be used to handle event processing methods in GUI event listeners, making the code more concise.

Advantages of Streams and Lambda Expressions

Using Streams and Lambda expressions has the following advantages:

  1. Simplicity: Using Stream and Lambda expressions can make the code more concise and readable, and reduce the complexity of the code.
  2. Easy to maintain: Using Stream and Lambda expressions can make the code easier to maintain and reduce code duplication.
  3. Concurrent execution: Stream streams can support concurrent execution and improve program execution efficiency.
  4. Efficient: Using Streams and Lambda expressions can make the code more efficient and reduce memory and CPU overhead.

in conclusion

Streams and Lambda expressions are two important features in Java 8. They can make the code more concise, readable, and flexible, and at the same time improve the efficiency and maintainability of the code. If you haven't used Streams and Lambda expressions yet, I hope this tutorial will help you get started.

Guess you like

Origin blog.csdn.net/xiangyuWA/article/details/129632852