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)