简体   繁体   English

在java 8中传递供应商而不是函数作为参数

[英]Passing Supplier instead of Function as argument in java 8

I want to filter out duplicates on the basis of some attributes in Person class.我想根据 Person 类中的某些属性过滤掉重复项。 I have a method definition as below :我有一个方法定义如下:

 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;
  };
 }

And the call to above method is made like this:对上述方法的调用是这样的:

    List<Person> distinctPersons = list.stream()
      .filter(distinctByKeys(Person::getFirstName, Person::getLastName))
      .collect(Collectors.toList());

In the method definition i can see the arguments can be Function implementations but the parameters passed in the above code are Supplier type (as they are returning a result and not taking any arg. But this works fine. How is it working can anyone explain.在方法定义中,我可以看到参数可以是函数实现,但在上面的代码中传递的参数是供应商类型(因为它们返回结果并且不接受任何参数。但这工作正常。任何人都可以解释它是如何工作的。

If you use a method reference using Type::method , where method is non-static, there is an explicit argument for the object to call the method on.如果使用Type::method使用方法引用,其中method是非静态的,则对象有一个显式参数来调用该方法。 In your case, Person::getFirstName is similar to (Person p) -> p.getFirstName() .在您的情况下, Person::getFirstName类似于(Person p) -> p.getFirstName()

the parameters passed in the above code are Supplier type (as they are returning a result and not taking any arg . But this works fine. How is it working can anyone explain.上面代码中传递的参数是Supplier类型(因为它们返回结果而不采用任何 arg 。但这很好用。任何人都可以解释它是如何工作的。

In the following code:在以下代码中:

.filter(distinctByKeys(Person::getFirstName, Person::getLastName))

Method references Person::getFirstName and Person::getLastName are not of type Supplier , these are Funtion s because they do require an argument of type Person in order to return a person's first name or last name .方法引用Person::getFirstNamePerson::getLastName不是Supplier类型,它们是Funtion ,因为它们确实需要Person类型的参数才能返回一个人的名字姓氏

In the first example I simply assigned distinctByKeys and forSupplier methods to Function interface.在第一个示例中,我只是将 distinctByKeys 和 forSupplier 方法分配给 Function 接口。 Then I just apply(execute) method with apply method by given parameters.然后我只是通过给定参数应用(执行)方法和应用方法。

Also supplier can be used as you can see from the second example.正如您从第二个示例中看到的那样,也可以使用供应商。 Last example is yours.最后一个例子是你的。 But I have a question.但我有一个问题。

Map instantionation in the distinctByKeys method is a little bit suspicious. distinctByKeys 方法中的映射实例化有点可疑。 I just can imagine that map is instantiated when each person is called by filter method so It means that it will return true each time because map is empty and there is no keys in the map which is queried by seen.putIfAbsent(keys, Boolean.TRUE) method call.我可以想象当每个人都被过滤器方法调用时,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM