
本文介绍了如何使用 Java Stream API 中的 filter 方法,结合多个函数式接口(Predicate)来实现复杂的过滤逻辑。重点讲解了如何将多个 Predicate 组合成一个,以满足不同的过滤需求,例如:所有条件都满足、至少一个条件满足等。同时,也指出了自定义函数式接口的必要性,并推荐使用 Java 内置的 Predicate 接口。
Java 8 引入了函数式接口 Predicate,它表示一个布尔值函数,接受一个参数并返回一个布尔值。Predicate 非常适合用于 Stream 的 filter 操作,可以方便地定义各种过滤条件。
例如,假设我们有一个 Student 类,并且想要过滤出所有年龄大于 18 岁的学生:
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Getter;
class Student {
@Getter
private LocalDate birthDate;
public Student(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
public class PredicateExample {
public static void main(String[] args) {
List<Student> students = List.of(
new Student(LocalDate.of(2000, 1, 1)),
new Student(LocalDate.of(2005, 1, 1)),
new Student(LocalDate.of(1995, 1, 1))
);
Predicate<Student> isAdult = s -> ChronoUnit.YEARS.between(LocalDate.now(), s.getBirthDate()) >= 18;
List<Student> adultStudents = students.stream()
.filter(isAdult)
.collect(Collectors.toList());
System.out.println("Adult Students Count: " + adultStudents.size()); // Output: 3
}
}当需要应用多个过滤条件时,可以将多个 Predicate 组合成一个。Predicate 接口提供了 and、or 和 negate 方法来实现逻辑与、逻辑或和逻辑非操作。
立即学习“Java免费学习笔记(深入)”;
1. 所有条件都满足(逻辑与)
如果需要所有条件都满足,可以使用 Predicate.and() 方法。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Getter;
class Student {
@Getter
private LocalDate birthDate;
@Getter
private String name;
public Student(LocalDate birthDate, String name) {
this.birthDate = birthDate;
this.name = name;
}
}
public class CombinedPredicateExample {
public static void main(String[] args) {
List<Student> students = List.of(
new Student(LocalDate.of(2000, 1, 1), "Alice"),
new Student(LocalDate.of(2005, 1, 1), "Bob"),
new Student(LocalDate.of(1995, 1, 1), "Charlie"),
new Student(LocalDate.of(2000, 1, 1), "David")
);
Predicate<Student> isAdult = s -> ChronoUnit.YEARS.between(LocalDate.now(), s.getBirthDate()) >= 18;
Predicate<Student> nameStartsWithA = s -> s.getName().startsWith("A");
Predicate<Student> combinedPredicate = isAdult.and(nameStartsWithA);
List<Student> filteredStudents = students.stream()
.filter(combinedPredicate)
.collect(Collectors.toList());
System.out.println("Filtered Students Count: " + filteredStudents.size()); // Output: 1
}
}2. 至少一个条件满足(逻辑或)
如果只需要至少一个条件满足,可以使用 Predicate.or() 方法。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Getter;
class Student {
@Getter
private LocalDate birthDate;
@Getter
private String name;
public Student(LocalDate birthDate, String name) {
this.birthDate = birthDate;
this.name = name;
}
}
public class CombinedPredicateExample {
public static void main(String[] args) {
List<Student> students = List.of(
new Student(LocalDate.of(2000, 1, 1), "Alice"),
new Student(LocalDate.of(2005, 1, 1), "Bob"),
new Student(LocalDate.of(1995, 1, 1), "Charlie"),
new Student(LocalDate.of(2000, 1, 1), "David")
);
Predicate<Student> isAdult = s -> ChronoUnit.YEARS.between(LocalDate.now(), s.getBirthDate()) >= 18;
Predicate<Student> nameStartsWithA = s -> s.getName().startsWith("A");
Predicate<Student> combinedPredicate = isAdult.or(nameStartsWithA);
List<Student> filteredStudents = students.stream()
.filter(combinedPredicate)
.collect(Collectors.toList());
System.out.println("Filtered Students Count: " + filteredStudents.size()); // Output: 4
}
}3. 使用循环组合多个 Predicate
如果 Predicate 的数量很多,可以使用循环来组合它们。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Getter;
class Student {
@Getter
private LocalDate birthDate;
@Getter
private String name;
public Student(LocalDate birthDate, String name) {
this.birthDate = birthDate;
this.name = name;
}
}
public class CombinedPredicateExample {
public static void main(String[] args) {
List<Student> students = List.of(
new Student(LocalDate.of(2000, 1, 1), "Alice"),
new Student(LocalDate.of(2005, 1, 1), "Bob"),
new Student(LocalDate.of(1995, 1, 1), "Charlie"),
new Student(LocalDate.of(2000, 1, 1), "David")
);
List<Predicate<Student>> predicates = new ArrayList<>();
predicates.add(s -> ChronoUnit.YEARS.between(LocalDate.now(), s.getBirthDate()) >= 18);
predicates.add(s -> s.getName().startsWith("A"));
predicates.add(s -> s.getName().length() > 3);
Predicate<Student> combinedPredicate = predicates.stream()
.reduce(Predicate.isEqual(true), Predicate::and);
List<Student> filteredStudents = students.stream()
.filter(combinedPredicate)
.collect(Collectors.toList());
System.out.println("Filtered Students Count: " + filteredStudents.size()); // Output: 1
}
}通常情况下,没有必要自定义类似 FilterClass 的函数式接口。Java 已经提供了 Predicate 接口,它已经满足了大多数过滤需求。自定义接口会增加代码的复杂性,并且没有带来额外的优势。
通过本文,我们学习了如何使用 Java Stream API 中的 filter 方法,结合多个 Predicate 来实现复杂的过滤逻辑。我们了解了如何使用 and、or 和循环来组合多个 Predicate,并避免自定义重复的函数式接口。掌握这些技巧可以帮助我们编写更加简洁、高效的 Java 代码。
以上就是使用 Java Stream 过滤器应用多个函数式接口的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号