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

Pet*_*all 1 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));
}
Run Code Online (Sandbox Code Playgroud)

但它失败并出现错误:

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>

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

Pet*_*all 6

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

\n\n

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

\n\n

Predicate<T>可能存在,因为有时您可能希望使用以下方法组成谓词:and、or和negate,而这些方法在 上没有意义Function<T, U>。Java 不允许只为可能的通用参数的子集定义方法,因此谓词更符合人体工学建模Predicate<T>而不是Function<T, Boolean>针对常见用例。

\n\n

为谓词提供单独接口的另一个原因是 Java 不允许在泛型参数中使用基元。这意味着您不能将谓词定义为Function<T, boolean>\xe2\x80\x94 它必须是Function<T, Boolean>,因此谓词的调用者必须处理null返回值的可能性。使用专门的接口允许 的返回值test改为 a boolean,并允许调用者假设结果是 never null。

\n\n

我原来的用例中可能的替代品是,它可以在需要或 的Boolean::booleanValue地方使用。Predicate<Boolean>Function<Boolean, Boolean>

\n


Ant*_*iuc 5

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

在这种情况下可能会令人困惑的是,即使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;
Run Code Online (Sandbox Code Playgroud)