通用 "is null" 谓词
Generic "is null" predicate
我写了这个通用谓词:
private static <T> Predicate<T> isNull(){
return Objects::isNull;
}
但我不能像这样将它与其他谓词结合使用:
private static Predicate<String> isEmpty(){
return string -> string.isEmpty();
}
因为这个片段不会编译(期望 Predicate in or 操作):
isNull().or(isEmpty())
有解决办法吗?谢谢!
由于isNull()
是泛型,编译器无法在这样组合时推断出泛型参数,因此您需要显式指定类型参数。
为此,您必须使用 class 名称进行限定,例如Test
:
Test.<String>isNull().or(isEmpty())
完整示例:
public class Test {
public static void main(String[] args) {
Predicate<String> isNullOrEmpty = Test.<String>isNull().or(isEmpty());
System.out.println(isNullOrEmpty.test(null)); // true
System.out.println(isNullOrEmpty.test("")); // true
System.out.println(isNullOrEmpty.test("Foo")); // false
}
private static <T> Predicate<T> isNull(){
return Objects::isNull;
}
private static Predicate<String> isEmpty(){
return string -> string.isEmpty();
}
}
您也可以通过将每个部分分配给一个变量来解决它:
Predicate<String> isNull = isNull(); // String is inferred from assignment operator
Predicate<String> isEmpty = isEmpty();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty);
或者只是第一部分:
Predicate<String> isNull = isNull();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty());
当您调用 isNull()
时,没有上下文可以推断出 T
的实际类型。
isNull().or(..)
这里需要一个 Predicate<? super Object>
,因此你不能将 Predicate<String>
传递给它。
翻转它们就可以了 (isEmpty().or(isNull())
)
isEmpty()
现在 returns 一个 Predicate<String>
和 isEmpty.or(..)
期望一个 Predicate<? super String>
所以你可以传递一个 Predicate<Object>
但这不是你想要的,因为你想在检查是否为空之前进行空检查(感谢 Slaw@ 指出这一点。专注于使其编译我没有注意它的meaning/semantic)。
你可以通过写
给编译器提示类型T
是什么
<YourClassName>.<String>isNull().or(isEmpty());
专门针对 String
,您可能只是在寻找像这样的单个 Predicate
-
private static Predicate<String> isNullOrEmpty() {
return s -> s == null || s.isEmpty();
}
这可以进一步用作
List<String> strings = Arrays.asList("", "one", "two", null, "three");
strings.stream().filter(isNullOrEmpty()).forEach(System.out::println);
// ofcourse the above would print "null" and is less useful
或者在 Java11 中使用 Predicate.not
的能力,更直观和看似有用的方法是 -
List<String> strings = Arrays.asList("", "one", "two", null, "three");
strings.stream().filter(Predicate.not(isNullOrEmpty)).forEach(System.out::println);
// this would print one, two and three
在我们的项目中,我们有一个小的解决方法:
private static <T> Predicate<T> allOr(Predicate<T> ... predicates) {
return Arrays.stream(predicates).reduce(Predicate::or).orElse(x -> true);
}
并将其用于:
Predicate<String> both = allOr(isEmpty(), isNull());
我写了这个通用谓词:
private static <T> Predicate<T> isNull(){
return Objects::isNull;
}
但我不能像这样将它与其他谓词结合使用:
private static Predicate<String> isEmpty(){
return string -> string.isEmpty();
}
因为这个片段不会编译(期望 Predicate
isNull().or(isEmpty())
有解决办法吗?谢谢!
由于isNull()
是泛型,编译器无法在这样组合时推断出泛型参数,因此您需要显式指定类型参数。
为此,您必须使用 class 名称进行限定,例如Test
:
Test.<String>isNull().or(isEmpty())
完整示例:
public class Test {
public static void main(String[] args) {
Predicate<String> isNullOrEmpty = Test.<String>isNull().or(isEmpty());
System.out.println(isNullOrEmpty.test(null)); // true
System.out.println(isNullOrEmpty.test("")); // true
System.out.println(isNullOrEmpty.test("Foo")); // false
}
private static <T> Predicate<T> isNull(){
return Objects::isNull;
}
private static Predicate<String> isEmpty(){
return string -> string.isEmpty();
}
}
您也可以通过将每个部分分配给一个变量来解决它:
Predicate<String> isNull = isNull(); // String is inferred from assignment operator
Predicate<String> isEmpty = isEmpty();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty);
或者只是第一部分:
Predicate<String> isNull = isNull();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty());
当您调用 isNull()
时,没有上下文可以推断出 T
的实际类型。
isNull().or(..)
这里需要一个 Predicate<? super Object>
,因此你不能将 Predicate<String>
传递给它。
翻转它们就可以了 (isEmpty().or(isNull())
)
isEmpty()
现在 returns 一个 Predicate<String>
和 isEmpty.or(..)
期望一个 Predicate<? super String>
所以你可以传递一个 Predicate<Object>
但这不是你想要的,因为你想在检查是否为空之前进行空检查(感谢 Slaw@ 指出这一点。专注于使其编译我没有注意它的meaning/semantic)。
你可以通过写
给编译器提示类型T
是什么
<YourClassName>.<String>isNull().or(isEmpty());
专门针对 String
,您可能只是在寻找像这样的单个 Predicate
-
private static Predicate<String> isNullOrEmpty() {
return s -> s == null || s.isEmpty();
}
这可以进一步用作
List<String> strings = Arrays.asList("", "one", "two", null, "three");
strings.stream().filter(isNullOrEmpty()).forEach(System.out::println);
// ofcourse the above would print "null" and is less useful
或者在 Java11 中使用 Predicate.not
的能力,更直观和看似有用的方法是 -
List<String> strings = Arrays.asList("", "one", "two", null, "three");
strings.stream().filter(Predicate.not(isNullOrEmpty)).forEach(System.out::println);
// this would print one, two and three
在我们的项目中,我们有一个小的解决方法:
private static <T> Predicate<T> allOr(Predicate<T> ... predicates) {
return Arrays.stream(predicates).reduce(Predicate::or).orElse(x -> true);
}
并将其用于:
Predicate<String> both = allOr(isEmpty(), isNull());