Java Stream filter()的用法(附带实例)
filter() 方法是 Java Stream 接口提供的过滤方法。该方法可以将 lambda 表达式作为参数,然后按照 lambda 表达式的逻辑过滤流中的元素。过滤出想要的流元素后,还需使用 Stream 提供的 collect() 方法按照指定方法重新进行封装。
【实例 1】输出 1~10 的所有奇数。将 1~10 的数字放到一个 ArrayList 列表中,调用该列表的 Stream 对象的 filter() 方法,该方法的参数为过滤奇数的 lambda 表达式。查看该方法被执行完毕后 Stream 对象返回的结果。
代码在 Eclipse 中出现黄色警告,这是由 printeach(String message, List list) 方法中的 list 参数没有指定泛型引起的。但是,这也体现出 lambda 表达式可以自动识别数据类型的优点。读者可以忽略此警告。
实例 1 中演示的集合元素是数字类型,集合能保存的不止是数字,下面这个实例将演示如何利用过滤器以对象属性为条件过滤元素。
【实例 2】找出年龄大于 30 的员工。本例使用了如下定义的 Employee 类:
在获取员工集合后,将年龄大于 30 的员工过滤出来。如果将员工集合返回的流对象泛型定义为 <Employee>,就可以直接在 lambda 表达式中使用 Employee 类的方法。
【实例 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
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=人事部