具有过滤条件工作流的Java 8流

时间:2018-08-22 12:36:44

标签: java lambda java-8 java-stream

在具有过滤条件的Java 8流中,集合中的每个元素都传递给过滤器以检查条件。在这里,我正在编写两个不同的过滤条件并提供不同的工作流程。

Maven

在上面的示例代码中,语句第1行过滤条件仅执行一次,而第2行对集合输出中的每个元素都执行。

我认为public static void main(String[] args) { List<String> asList = Arrays.asList("a", "b", "c", "d", "e", "a", "b", "c"); //line 1 asList.stream().map(s -> s).filter(distinctByKey(String::toString)).forEach(System.out::println); Predicate<String> strPredicate = (a) -> { System.out.println("inside strPredicate method--"); return a.startsWith("a"); }; //line 2 asList.stream().filter(strPredicate).forEach(System.out::println); } public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) { System.out.println("inside distinctByKey method..."); Set<Object> seen = ConcurrentHashMap.newKeySet(); return t -> seen.add(keyExtractor.apply(t)); } 方法将对集合中的每个元素执行,但事实并非如此。为什么?

distinctByKey对象引用变量Set仅执行一次吗?流程如何运作?

2 个答案:

答案 0 :(得分:17)

distinctByKey是lambda工厂方法。它是返回一个Predictate<T>

因此,当您执行:filter(distinctByKey(String::toString))时,实际上是在首先调用distinctByKey方法,然后 返回一个Predicate。然后,该谓词将为每个元素执行。只是工厂功能只会执行一次。

在返回的lambda中移动System.out.println时,您将获得所需的打印语句:

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    System.out.println("inside distinctByKey method...");
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> {
        System.out.println("inside distinctByKey.lambda method... ");
        return seen.add(keyExtractor.apply(t));
    };
}

答案 1 :(得分:4)

一旦返回Predicate-{{1},则Predicate::test被lambda表达式捕获并被lambda内 cached 捕获}将与seen

相同实例多次调用