时间:2023-01-17 12:46:51 | 栏目:JAVA代码 | 点击:次
本文介绍Java 8 Predicate链.
怎么使用简单的Predicate来过滤list中的name
@Test public void whenFilterList_thenSuccess(){ List<String> names = Arrays.asList("Adam", "Alexander", "John", "Tom"); List<String> result = names.stream() .filter(name -> name.startsWith("A")) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }
我们使用Predicate来筛选以大写字母A开头的姓名。
name -> name.startsWith("A")
那么如果多个条件这么办?
@Test public void whenFilterListWithMultipleFilters_thenSuccess(){ List<String> result = names.stream() .filter(name -> name.startsWith("A")) .filter(name -> name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }
用两个filter传入两个 Predicate分别过滤 【以A开头的】和【姓名长度小于5】的。
@Test public void whenFilterListWithComplexPredicate_thenSuccess(){ List<String> result = names.stream() .filter(name -> name.startsWith("A") && name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }
使用一个 filter 传入复杂的Predicate.
Predicates可以将 Predicate.and(), Predicate.or() 和 Predicate.negate()组合起来使用。
@Test public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){ Predicate<String> predicate1 = str -> str.startsWith("A"); Predicate<String> predicate2 = str -> str.length() < 5; List<String> result = names.stream() .filter(predicate1.and(predicate2)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }
两个条件都要满足
满足其中一个即可
@Test public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){ Predicate<String> predicate1 = str -> str.startsWith("J"); Predicate<String> predicate2 = str -> str.length() < 4; List<String> result = names.stream() .filter(predicate1.or(predicate2)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("John","Tom")); }
将此条件取反
Predicate<String> predicate2 = str -> str.length() < 4;
相当于
Predicate<String> predicate2 = str -> str.length() >= 4;
@Test public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){ Predicate<String> predicate1 = str -> str.startsWith("J"); Predicate<String> predicate2 = str -> str.length() < 4; List<String> result = names.stream() .filter(predicate1.or(predicate2.negate())) .collect(Collectors.toList()); assertEquals(3, result.size()); assertThat(result, contains("Adam","Alexander","John")); }
@Test public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){ List<String> result = names.stream() .filter(((Predicate<String>)name -> name.startsWith("A")) .and(name -> name.length()<5)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }
在开始介绍之前,简单介绍下 reduce 函数:
`java.util.stream.Stream#reduce(T, java.util.function.BinaryOperator<T>)`
源码的注释中给出等价的写法:
T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
即,第一个参数当做初始值,后续参数和第一个参数进行运算,最终得到结果。
接下来我们看下面 reduce 中 and 操作的例子:
@Test public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){ List<Predicate<String>> allPredicates = new ArrayList<Predicate<String>>(); allPredicates.add(str -> str.startsWith("A")); allPredicates.add(str -> str.contains("d")); allPredicates.add(str -> str.length() > 4); List<String> result = names.stream() .filter(allPredicates.stream().reduce(x->true, Predicate::and)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Alexander")); }
注意这里初始条件是 true (如果初始条件为 false ,后续即使都满足,和初始值一起 and ,也没结果)
然后看 reduce 中使用 or 操作的例子:
@Test public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){ List<String> result = names.stream() .filter(allPredicates.stream().reduce(x->false, Predicate::or)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }
Predicate::or 操作,通常会将初始值设置为 false,因为如果初始值为 true 不管后续条件是否为 true 最终结果都为 true。
本文介绍Java 8 Predicate。介绍了 Predicate在Stream的filter函数中的运用。讲述了复杂的Predicate或者Predicate的组合的用法。