Lambda 与流一起使用的功能接口实现之间的差异
我在这里试图了解过滤流的工作原理。 下面是从Lambda 与流一起使用的功能接口实现之间的差异,lambda,java-8,functional-programming,java-stream,Lambda,Java 8,Functional Programming,Java Stream,我在这里试图了解过滤流的工作原理。 下面是从Strings的List中筛选重复项的两种方法。 (我不想使用distinct关键字进行说明) 这种方法似乎奏效了。不确定方法1和方法2之间的区别。我看到distincyByKey是一个静态方法,但是它有什么区别呢?每次执行lambda表达式体时,您的第一个代码片段都会创建一个新的集实例,这意味着流的每个元素都有一个实例。因此,每次在流的元素上应用过滤器时,它都会将该元素添加到不同的集合实例中,因此无法过滤出重复项 在第二个代码段中,执行distinc
String
s的List
中筛选重复项的两种方法。
(我不想使用distinct关键字进行说明)
这种方法似乎奏效了。不确定方法1和方法2之间的区别。我看到
distincyByKey
是一个静态方法,但是它有什么区别呢?每次执行lambda表达式体时,您的第一个代码片段都会创建一个新的集
实例,这意味着流的每个元素都有一个实例。因此,每次在流
的元素上应用过滤器时,它都会将该元素添加到不同的集合
实例中,因此无法过滤出重复项
在第二个代码段中,执行distincyByKey()
时,将创建一次Set
实例。当对流的每个元素计算过滤器时,执行的lambda主体就是seen.add(keydectractor.apply(t)
,并且它总是针对相同的Set
实例执行
通过在流管道外部创建Set
实例,或者使用方法引用,可以在没有static
方法的情况下实现相同的行为:
Set<String> seen = ConcurrentHashMap.newKeySet();
List<String> list1 =
list.parallelStream().filter(e-> seen.add(e)).collect(Collectors.toList());
Set seen=ConcurrentHashMap.newKeySet();
列表1=
list.parallelStream().filter(e->seen.add(e)).collect(Collectors.toList());
或
列表列表1=
list.parallelStream().filter(ConcurrentHashMap.newKeySet()::add.collect(Collectors.toList());
编辑:我从代码中删除了getLastName()
方法调用,因为您的Stream
是Stream
,而String
s没有getLastName()
方法。我猜您混淆了一些代码片段。两者之间的区别恰恰在于您的Set
对象
在第一个代码段中,seen
是由谓词创建的。每个元素都会调用谓词。这意味着每次调用谓词时,都会创建一个集合实例。在第二个代码段中,集合是由distincyByKey()
创建的,它在创建流时只运行一次
distincyByKey
返回的谓词包含对该集合的引用,每次运行时,它都使用相同的实例。如果要使第二个代码像第一个一样运行,则该方法如下所示:
public static <T> Predicate<T> distincyByKey(Function<? super T, ?> keyExtractor) {
return t -> {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return seen.add(keyExtractor.apply(t));
}
}
公共静态谓词distincyByKey(函数键提取器){
返回t->{
Set seen=ConcurrentHashMap.newKeySet();
返回seen.add(keydextractor.apply(t));
}
}
此版本将与您的第一个实现一样被破坏。非常感谢。您能告诉我它是否在lambda或streams的功能中指定吗?@user2296988我不确定您希望看到指定的具体内容。需要了解的重要一点是代码的每个语句何时执行。参数传递给当创建流时,filter()
将被计算一次。传递给filter()
的谓词的test()
方法将对流的每个元素执行一次。一旦您确定了代码的哪一部分将成为该测试()的实现
方法在每个代码段中,您将看到差异。哦,这是有意义的。因此,通常lambda应该只有参数和返回语句(或void)。如果它在主体实现中有任何实例变量,它也会被视为参数。谢谢。请解释是否有任何方法可以使用您的第二个apporach作为成员变量。例如,我正在将一个类的变量传递到谓词。@user2296988我必须查看实际的示例代码。从com中还不够清楚哦,哇,从来都不知道你能用这种方式写回执。好帖子!
Set<String> seen = ConcurrentHashMap.newKeySet();
List<String> list1 =
list.parallelStream().filter(e-> seen.add(e)).collect(Collectors.toList());
List<String> list1 =
list.parallelStream().filter(ConcurrentHashMap.newKeySet()::add).collect(Collectors.toList());
public static <T> Predicate<T> distincyByKey(Function<? super T, ?> keyExtractor) {
return t -> {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return seen.add(keyExtractor.apply(t));
}
}