我有一些看起来像这样的代码(这里简化了):
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>
这里发生了什么,为什么要这样设计?
总结一下评论,我可以回答我自己的问题。
\n\nPredicate<T>与 无关Function<T, Boolean>,并且它们不能在彼此的位置中使用,即使它通常看起来具有逻辑意义。
Predicate<T>可能存在,因为有时您可能希望使用以下方法组成谓词:and、or和negate,而这些方法在 上没有意义Function<T, U>。Java 不允许只为可能的通用参数的子集定义方法,因此谓词更符合人体工学建模Predicate<T>而不是Function<T, Boolean>针对常见用例。
为谓词提供单独接口的另一个原因是 Java 不允许在泛型参数中使用基元。这意味着您不能将谓词定义为Function<T, boolean>\xe2\x80\x94 它必须是Function<T, Boolean>,因此谓词的调用者必须处理null返回值的可能性。使用专门的接口允许 的返回值test改为 a boolean,并允许调用者假设结果是 never null。
我原来的用例中可能的替代品是,它可以在需要或 的Boolean::booleanValue地方使用。Predicate<Boolean>Function<Boolean, Boolean>
这里的主要问题是类型不正确。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)
| 归档时间: |
|
| 查看次数: |
2578 次 |
| 最近记录: |