在这份详细的指南中,您将了解 Java Predicates,这是 Java 8 中一个新颖且有用的特性。本文解释了 Java Predicates 是什么以及如何在各种情况下使用它们。
在这份详尽的指南中,您将深入了解 Java Predicates,这是 Java 8 中引入的一项新颖且实用的功能。本文不仅阐释了 Java Predicates 的本质,还展示了如何在多种场景下灵活运用它们。
通过本指南,您将掌握过滤数据、链接 Predicates 以及规避常见错误的全部技巧。借助 Java Predicates,您不仅能显著提升 Java 编程技艺,还能将您的应用程序推向新的高度。
Predicates 是什么?
在 Java 8 中,Predicate 作为功能接口在 java.util.function 包中被引入。它代表一种布尔值函数,接受一个参数并返回真或假。Predicate 接口定义了一个名为 test() 的单一抽象方法,专门用于评估布尔条件。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
通常,Predicate 是过滤或评估集合中元素的得力工具。
入门指南
Java Predicate 作为一种功能接口,可以通过 lambda 表达式轻松定义。以下是一个简单的 Predicate 示例,用于判断字符串的长度是否为偶数:
Predicate<String> startWithLetterN = s -> s.startsWith("N");
在这段代码中,startWithLetterN 是一个 Predicate,它接受一个字符串 s 并检查其是否以字母 N 开头。我们通过 lambda 表达式 s -> s.startsWith(“N”) 来实现这一逻辑。
一旦定义了 Predicate,我们便可以利用其 test() 方法来评估数据。
Boolean result = startWithLetterN.test("Mateo");
@Test
void verify() {
assertThat(result).isFalse();
}
链接 Predicates
对Predicate进行链接操作非常简单,可以通过在第一个Predicate上调用 and 方法并将第二个Predicate作为参数传递来实现。
Predicate<String> startWithLetterP = s -> s.startsWith("P");
Predicate<String> lengthGreaterThan5 = s -> s.length() > 5;
Predicate<String> startWithPAndGreaterThan5 = startWithLetterP.and(lengthGreaterThan5);
@Test
void check() {
assertThat(startWithPAndGreaterThan5.test("Penelope")).isTrue();
}
使用 Predicate 过滤数据
谓词常用于过滤数据。例如,您可以使用它们来过滤符合特定条件的集合项。以下是一个使用 Predicate 过滤数字列表的示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Predicate<Integer> isGreaterThan4 = n -> n > 4;
Predicate<Integer> isEven = n -> n % 2 == 0;
List<Integer> matchingNumbers = numbers.stream()
.filter(isEven.and(isGreaterThan4))
.collect(Collectors.toList());
@Test
void check() {
assertThat(matchingNumbers).hasSize(3).containsExactly(6, 8, 10);
}
您可以使用不同的谓词方法来满足您的所有用例。
Java Predicates 提供了一些优势,它们更加灵活,因为它们可以作为参数传递并在方法中作为结果返回。它们还可以在不同的上下文中组合和重用。
例如,一旦我们有了一个像 startWithLetterN 这样的 Predicate,我们就可以在代码的多个地方使用它。这是在循环内部或 Stream 的 filter() 方法中定义的条件无法实现的。
总之,虽然循环和 Streams 可以用于在 Java 中过滤数据,但 Predicates 提供了更灵活和可重用的方法,特别是对于复杂条件和大型应用程序。
需要避免的坑
使用 Java Predicates 时存在潜在的陷阱。最常见的是使用方法引用时的 NullPointerExceptions。这通常发生在处理包含空值的集合时。
List<String> categories = Arrays.asList("Culture", "Entertainment", null);
Predicate<String> isShortWord = s -> s.length() < 4;
@Test
void check() {
categories.stream()
.filter(isShortWord)
.forEach(System.out::println);
}
在这个例子中,我们试图过滤一个字符串列表,只检索那些包含短单词的字符串。然而,我们的列表包含一个空值,这在我们尝试对其调用 length() 方法时会导致 NullPointerException。
为了避免这个问题,您可以在 Predicate 中添加另一个检查以忽略空值:
List<String> categories = Arrays.asList("Culture", "Entertainment", null);
Predicate<String> isShortWord = s -> Objects.nonNull(s) && s.length() < 4;
@Test
void check() {
categories.stream()
.filter(isShortWord)
.forEach(System.out::println);
}
另一个需要避免的陷阱是使用 Predicate 进行链接操作的顺序。当使用 and()、or() 和 negate() 链接 Predicates 时,请记住操作顺序会影响结果。
例如,在处理空值时,and() 操作不具有交换性:
总结
本文作为您掌握 Java Predicates 的综合指南。您已经深入了解了它们的工作原理、在 Java 编程中的重要性以及如何在代码中巧妙地运用它们。
通过阅读本指南,您不仅熟悉了 Java Predicates 的基础知识,还掌握了一些高级技巧,使您能够在项目中自信而娴熟地应用这些知识。
没有回复内容