首页 > 编程笔记 > Java笔记 阅读:6

Java Stream filter()的用法(附带实例)

filter() 方法是 Java Stream 接口提供的过滤方法。该方法可以将 lambda 表达式作为参数,然后按照 lambda 表达式的逻辑过滤流中的元素。过滤出想要的流元素后,还需使用 Stream 提供的 collect() 方法按照指定方法重新进行封装。

【实例 1】输出 1~10 的所有奇数。将 1~10 的数字放到一个 ArrayList 列表中,调用该列表的 Stream 对象的 filter() 方法,该方法的参数为过滤奇数的 lambda 表达式。查看该方法被执行完毕后 Stream 对象返回的结果。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FilterOddDemo {
    static void printeach(String message, List list) { //输出集合元素
        System.out.print(message); //输出文字信息
        list.stream().forEach(n -> {
            System.out.print(n + " "); //使用 forEach 方法遍历集合并输出元素
        });
        System.out.println(); //换行
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(); //创建空数组
        for (int i = 1; i <= 10; i++) {
            list.add(i); //从 1 循环到 10 //给集合赋值
        }
        printeach("集合原有元素:", list); //输出集合元素
        Stream<Integer> stream = list.stream(); //获取集合流对象
        //将集合中的所有奇数过滤出来,把过滤结果重新赋值给流对象
        stream = stream.filter(n -> n % 2 == 1);
        //将流对象重新封装成一个 List 集合
        List<Integer> result = stream.collect(Collectors.toList());
        printeach("过滤之后的集合元素:", result); //输出集合元素
    }
}
运行结果如下:

集合原有元素:1 2 3 4 5 6 7 8 9 10
过滤之后的集合元素:1 3 5 7 9

这个实例把“获取流”“过滤流”“封装流”3个部分的操作分开编写,是为了方便读者学习理解,通常为了代码简洁,将 3 部分操作可以写在一行代码中,例如:
List<Integer> result = list.stream().filter(n -> n % 2 == 1).collect(Collectors.toList());
这种写法也可以避免终端操作造成的“流被消费掉”的问题,因为每次被操作的流都是从集合中重新获取的。

代码在 Eclipse 中出现黄色警告,这是由 printeach(String message, List list) 方法中的 list 参数没有指定泛型引起的。但是,这也体现出 lambda 表达式可以自动识别数据类型的优点。读者可以忽略此警告。

实例 1 中演示的集合元素是数字类型,集合能保存的不止是数字,下面这个实例将演示如何利用过滤器以对象属性为条件过滤元素。

【实例 2】找出年龄大于 30 的员工。本例使用了如下定义的 Employee 类:
import java.util.ArrayList;
import java.util.List;

public class Employee {
    private String name; // 姓名
    private int age; // 年龄
    private double salary; // 工资
    private String sex; // 性别
    private String dept; // 部门

    // 构造方法
    public Employee(String name, int age, double salary, String sex, String dept) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.sex = sex;
        this.dept = dept;
    }

    // 重写 toString()方法,方便输出员工信息
    public String toString() {
        return "name=" + name + ", age=" + age + ", salary=" + salary + ", sex=" + sex + ", dept=" + dept;
    }

    // 以下是员工属性的 getter 方法
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getSalary() {
        return salary;
    }

    public String getSex() {
        return sex;
    }

    public String getDept() {
        return dept;
    }
    static List<Employee> getEmpList() { // 提供数据初始化方法
        List<Employee> list = new ArrayList<Employee>();
        list.add(new Employee("老张", 40, 9000, "男", "运营部"));
        list.add(new Employee("小刘", 24, 5000, "女", "开发部"));
        list.add(new Employee("大刚", 32, 7500, "男", "销售部"));
        list.add(new Employee("老李", 28, 5500, "女", "销售部"));
        list.add(new Employee("小马", 21, 3000, "男", "开发部"));
        list.add(new Employee("老王", 35, 6000, "女", "人事部"));
        list.add(new Employee("小王", 21, 3000, "女", "人事部"));
        return list;
    }
}

在获取员工集合后,将年龄大于 30 的员工过滤出来。如果将员工集合返回的流对象泛型定义为 <Employee>,就可以直接在 lambda 表达式中使用 Employee 类的方法。
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FilerDemo {
    public static void main(String[] args) {
        List<Employee> list = Employee.getEmpList(); //获取公共类的测试数据
        Stream<Employee> stream = list.stream(); //获取集合流对象
        stream = stream.filter(people -> people.getAge() > 30); //将年龄大于 30 岁的员工过滤出来
        List<Employee> result = stream.collect(Collectors.toList()); //将流对象重新封装成一个 List 集合
        for (Employee emp : result) { //遍历结果集
            System.out.println(emp); //输出员工对象信息
        }
    }
}
运行结果如下:

name=老张, age=40, salary=9000.0, sex=男, dept=运营部
name=大刚, age=32, salary=7500.0, sex=男, dept=销售部
name=老王, age=35, salary=6000.0, sex=女, dept=人事部

通过这个结果可以看出,年龄没超过 30 的员工都被过滤掉了。通过类的一个属性,就可以完整地获取到符合条件的类对象,可以输出员工的姓名、性别等属性。

相关文章