[英]Passing Supplier instead of Function as argument in java 8
我想根据 Person 类中的某些属性过滤掉重复项。 我有一个方法定义如下:
private static <T> Predicate<T> distinctByKeys(final Function<? super T, ?>... keyExtractors)
{
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
return t ->
{
final List<?> keys = Arrays.stream(keyExtractors)
.map(ke -> ke.apply(t))
.collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
对上述方法的调用是这样的:
List<Person> distinctPersons = list.stream()
.filter(distinctByKeys(Person::getFirstName, Person::getLastName))
.collect(Collectors.toList());
在方法定义中,我可以看到参数可以是函数实现,但在上面的代码中传递的参数是供应商类型(因为它们返回结果并且不接受任何参数。但这工作正常。任何人都可以解释它是如何工作的。
如果使用Type::method
使用方法引用,其中method
是非静态的,则对象有一个显式参数来调用该方法。 在您的情况下, Person::getFirstName
类似于(Person p) -> p.getFirstName()
。
上面代码中传递的参数是
Supplier
类型(因为它们返回结果而不采用任何 arg 。但这很好用。任何人都可以解释它是如何工作的。
在以下代码中:
.filter(distinctByKeys(Person::getFirstName, Person::getLastName))
方法引用Person::getFirstName
和Person::getLastName
不是Supplier
类型,它们是Funtion
,因为它们确实需要Person
类型的参数才能返回一个人的名字或姓氏。
在第一个示例中,我只是将 distinctByKeys 和 forSupplier 方法分配给 Function 接口。 然后我只是通过给定参数应用(执行)方法和应用方法。
正如您从第二个示例中看到的那样,也可以使用供应商。 最后一个例子是你的。 但我有一个问题。
distinctByKeys 方法中的映射实例化有点可疑。 我可以想象当每个人都被过滤器方法调用时,map 被实例化了,所以这意味着它每次都会返回 true,因为 map 是空的,并且 map 中没有被 seen.putIfAbsent(keys, Boolean. TRUE) 方法调用。
private static Predicate functionExample() {
Function<Function[], Predicate> f = Scratch::distinctByKeys;
Function<Supplier[], Predicate> f2 = Scratch::forSupplier;
f2.apply(new Supplier[0]);
return f.apply(new Function[0]);
}
private static <T> Predicate<T> forSupplier(final Supplier<? super T>... suppliers) {
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
return t ->
{
final List<?> keys = Arrays.stream(suppliers)
.map(Supplier::get)
.collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
private static <T> Predicate<T> distinctByKeys(final Function<? super T, ?>... keyFields)
{
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
return t ->
{
final List<?> keys = Arrays.stream(keyFields)
.map(ke -> ke.apply(t))
.collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.