为什么我不能在Optional.filter的参数中用Function.identity()替换(t - > t)?

时间:2017-05-04 14:33:49

标签: java java-8

我有一些看起来有点像这样的代码(这里简化了):

public Optional<String> parseInput(String input){
    Pattern pattern = Pattern.compile("([A-Za-z]+)([0-9]{2}|[0-9]{4})");
    Matcher matcher = pattern.matcher(input);
    return Optional.of(matcher.find())
                   .filter(t -> t) // .filter(Function.identity())
                   .map(ignore -> matcher.group(1));
}

但它失败并出现错误:

  

Error: incompatible types: no instance(s) of type variable(s) T exist so that java.util.function.Function<T,T> conforms to java.util.function.Predicate<? super java.lang.Boolean>

这里发生了什么,为什么这样设计?

2 个答案:

答案 0 :(得分:1)

总结评论,我可以回答我自己的问题。

Predicate<T>Function<T, Boolean>无关,并且它们不能在彼此的位置使用,即使它通常看起来具有逻辑意义。

Predicate<T>可能存在,因为有时您可能希望使用以下方法撰写谓词:andornegate,这些方法不会在Function<T, U>上有意义。 Java不允许仅为可能的通用参数的子集定义方法,因此对于常见用例,谓词更符合人体工程学Predicate<T>而不是Function<T, Boolean>

为谓词设置单独接口的另一个原因是Java不允许通用参数中的基元。这意味着您无法将谓词定义为Function<T, boolean> - 它必须是Function<T, Boolean>,因此谓词的调用者必须处理null返回值的可能性。使用专用接口允许test的返回值为boolean,并允许调用者假设结果永远不会null

原始用例中可能的替换为Boolean::booleanValue,可在需要Predicate<Boolean>Function<Boolean, Boolean>的地方使用。

答案 1 :(得分:1)

这里的主要问题是类型不正确。 Predicate不是Function,它不是Function的子接口,而是独立的功能接口。 Stream#filter接受Predicate作为参数:filter(Predicate<? super T> predicate)。由于PredicateFunction之间没有关系,因此我们无法将Functionfilter一起使用。

在这种情况下可能令人困惑的是,即使t -> t看起来与Function.identity()完全相同,也可能只是Function,但它可能不是Function。关于lambda表达式的一个重要事项是lambda本身并不包含有关其类型的任何信息。该信息是从上下文中推断出来的。相同的lambda可以表示不同的功能接口。

Predicate<Boolean> predicate = t -> t;
Function<Boolean,Boolean> function = t -> t;

Predicate<Boolean> predicateBoolean = Boolean::booleanValue;
Function<Boolean,Boolean> functionBoolean = Boolean::booleanValue;