我有一些看起来有点像这样的代码(这里简化了):
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>
这里发生了什么,为什么这样设计?
答案 0 :(得分:1)
总结评论,我可以回答我自己的问题。
Predicate<T>
与Function<T, Boolean>
无关,并且它们不能在彼此的位置使用,即使它通常看起来具有逻辑意义。
Predicate<T>
可能存在,因为有时您可能希望使用以下方法撰写谓词:and
,or
和negate
,这些方法不会在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)
。由于Predicate
和Function
之间没有关系,因此我们无法将Function
与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;