跳转至

Java Stream 和 Filter 深度解析

简介

在 Java 编程中,Java Stream 和 Filter 是 Java 8 引入的强大特性,它们为处理集合数据提供了一种更简洁、更高效、更函数式的方式。Stream 可以让我们以声明式的方式处理数据集合,而 Filter 则是 Stream 中常用的中间操作,用于筛选出符合特定条件的元素。本文将详细介绍 Java Stream 和 Filter 的基础概念、使用方法、常见实践以及最佳实践,帮助读者深入理解并高效使用它们。

目录

  1. Java Stream 和 Filter 基础概念
  2. Java Stream 和 Filter 使用方法
  3. Java Stream 和 Filter 常见实践
  4. Java Stream 和 Filter 最佳实践
  5. 小结
  6. 参考资料

1. Java Stream 和 Filter 基础概念

1.1 Java Stream

Java Stream 是一个来自数据源的元素队列并支持聚合操作。这里的数据源可以是集合、数组、I/O 通道等。Stream 并不会存储元素,它只是对数据源的元素进行一系列的操作,这些操作可以是中间操作(如 filter、map 等)或终端操作(如 collect、forEach 等)。Stream 操作是惰性的,只有在遇到终端操作时才会真正执行。

1.2 Java Filter

Filter 是 Stream 中的一个中间操作,它接收一个 Predicate(函数式接口)作为参数,用于筛选出符合 Predicate 条件的元素。Filter 操作会返回一个新的 Stream,其中只包含满足条件的元素。

2. Java Stream 和 Filter 使用方法

2.1 创建 Stream

可以通过多种方式创建 Stream,以下是一些常见的方法:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamCreationExample {
    public static void main(String[] args) {
        // 从集合创建 Stream
        List<String> list = Arrays.asList("apple", "banana", "cherry");
        Stream<String> streamFromList = list.stream();

        // 从数组创建 Stream
        String[] array = {"apple", "banana", "cherry"};
        Stream<String> streamFromArray = Arrays.stream(array);

        // 创建空 Stream
        Stream<String> emptyStream = Stream.empty();
    }
}

2.2 使用 Filter 进行筛选

以下是一个简单的使用 Filter 筛选出长度大于 5 的字符串的示例:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
        List<String> filteredList = list.stream()
                .filter(s -> s.length() > 5)
                .collect(Collectors.toList());
        System.out.println(filteredList);
    }
}

在上述示例中,filter(s -> s.length() > 5) 是一个 Filter 操作,它接收一个 Lambda 表达式作为 Predicate,筛选出长度大于 5 的字符串。最后,使用 collect(Collectors.toList()) 终端操作将筛选后的元素收集到一个新的列表中。

3. Java Stream 和 Filter 常见实践

3.1 筛选对象集合

假设我们有一个 Person 类,包含姓名和年龄属性,我们可以使用 Filter 筛选出年龄大于 18 的人:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

public class FilterObjectCollectionExample {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 20));
        people.add(new Person("Bob", 15));
        people.add(new Person("Charlie", 25));

        List<Person> adults = people.stream()
                .filter(person -> person.getAge() > 18)
                .collect(Collectors.toList());

        adults.forEach(person -> System.out.println(person.getName()));
    }
}

3.2 组合多个 Filter 操作

可以组合多个 Filter 操作来实现更复杂的筛选逻辑:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MultipleFilterExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
        List<String> filteredList = list.stream()
                .filter(s -> s.length() > 5)
                .filter(s -> s.startsWith("b"))
                .collect(Collectors.toList());
        System.out.println(filteredList);
    }
}

在上述示例中,我们先筛选出长度大于 5 的字符串,然后再筛选出以 "b" 开头的字符串。

4. Java Stream 和 Filter 最佳实践

4.1 尽早使用 Filter

为了提高性能,应该尽早使用 Filter 操作,减少后续操作需要处理的元素数量。例如:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class EarlyFilterExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
        // 尽早使用 Filter
        List<String> filteredList = list.stream()
                .filter(s -> s.length() > 5)
                .map(s -> s.toUpperCase())
                .collect(Collectors.toList());
        System.out.println(filteredList);
    }
}

在上述示例中,先使用 Filter 筛选出长度大于 5 的字符串,再进行 map 操作,这样 map 操作只需要处理筛选后的元素,提高了性能。

4.2 使用并行 Stream 提高性能

对于大规模数据集合,可以使用并行 Stream 来充分利用多核处理器的性能:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ParallelStreamExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
        List<String> filteredList = list.parallelStream()
                .filter(s -> s.length() > 5)
                .collect(Collectors.toList());
        System.out.println(filteredList);
    }
}

需要注意的是,并行 Stream 并不是在所有情况下都能提高性能,需要根据具体情况进行测试和选择。

小结

Java Stream 和 Filter 是 Java 8 引入的强大特性,它们为处理集合数据提供了一种更简洁、更高效、更函数式的方式。通过本文的介绍,我们了解了 Java Stream 和 Filter 的基础概念、使用方法、常见实践以及最佳实践。在实际开发中,合理使用 Java Stream 和 Filter 可以提高代码的可读性和性能。

参考资料