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

Lea*_*oop 3 java lambda java-8 java-stream

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

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));
}
Run Code Online (Sandbox Code Playgroud)

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

我认为该distinctByKey方法将对集合中的每个元素执行,但事实并非如此.为什么?

另外,Set对象引用变量seen是仅执行一次?流程如何工作?

Lin*_*ica 18

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

所以当你执行:filter(distinctByKey(String::toString))你实际上是distinctByKey先调用方法,然后返回一个Predicate.然后为每个元素执行该谓词.工厂功能只会执行一次.

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

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));
    };
}
Run Code Online (Sandbox Code Playgroud)