实用程序 Class 到 bootstrap lambda 表达式或方法链接的方法引用?
Utility Class to bootstrap lambda expressions or method references for method chaining?
使用 Java 8 中介绍的功能接口,您可以轻松地将不同的表达式链接成一个新的表达式,如下面的代码片段所示。
public class PredicateChaining {
public static void main(String[] args) {
// verbose, but standard JDK functionality only
Predicate<String> allUpperCase = StringUtils::isAllUpperCase;
Predicate<String> longerThan5 = s -> s.length() > 5;
if (allUpperCase.and(longerThan5).test("PREDICATE")) {
System.out.println("'PREDICATE' is a uppercase text, longer than 5.");
}
// compact, but with utility method ('chain' in this case)
if (chain(StringUtils::isAllLowerCase).and(s -> s.length() < 5).test("test")) {
System.out.println("'test' is a lowercase text, shorter than 5.");
}
}
public static <T> Predicate<T> chain(Predicate<T> test) {
return test;
}
}
在这种情况下,2 个字符串 Predicate 链接成一个新的 Predicate。当您至少有一个句柄(即变量)来调用链接方法(在本例中为“and”)时,这会很好地工作。但是,如果要链接的表达式表示为 lambda 或方法引用,则需要将其中之一显式转换为变量,这会非常冗长。当编译器无法确定确切的类型时,你不得不求助于这种构造。但在大多数情况下,这只是我想避免的冗长开销。
在这个例子中,我自己编写了实用方法'chain'。
但是我可以为其他功能接口创建一个 (Function, Consumer, Supplier, BiConsumer, ...) 以及。
我不想使用这些方法创建我自己的实用程序 class(我可能会将其复制粘贴到我从事的每个项目),我想知道这样的 class 是否存在于JDK 还是在某个图书馆?
另一方面,如果这样的 class 不存在并且我不应该自己创建一个,我想听听为什么。
创建 Predicate
个实例以在后续 if
语句中使用它们是没有意义的。
Predicate
实例通常用于将条件传递给方法。在这种情况下,您可以研究特定的 API 以了解是否可以使用自然结构进行这种链接。
例如将 Predicate
传递给流时,您可以简单地进行两次或更多次 filter
调用:
stringStream.filter(StringUtils::isAllUpperCase).filter(s->s.length()>5). …
(您可以类似地使用多个 map
调用来链接 Function
s)
和其他API可能有类似的方法。
但毕竟,如果您有两个要合并的条件,并且都不是 Predicate
实例,那么直接的解决方案就是合并表达式:
stringStream.filter(s -> isAllUpperCase(s) && s.length()>5). …
或作为独立创作:
Predicate<String> allUpperCaseAndLongerThan5 = s -> isAllUpperCase(s) && s.length()>5;
请注意,您可以在此处使用 static import
作为实用方法,这样可以使用更紧凑的表达式。
使用Predicate.and
和Predicate.or
仅当您已经有一个Predicate
实例并想扩充其逻辑时才有用。但在这种情况下,您还有一个实例,您可以在该实例上毫无问题地调用 and
或 or
。
使用 Java 8 中介绍的功能接口,您可以轻松地将不同的表达式链接成一个新的表达式,如下面的代码片段所示。
public class PredicateChaining {
public static void main(String[] args) {
// verbose, but standard JDK functionality only
Predicate<String> allUpperCase = StringUtils::isAllUpperCase;
Predicate<String> longerThan5 = s -> s.length() > 5;
if (allUpperCase.and(longerThan5).test("PREDICATE")) {
System.out.println("'PREDICATE' is a uppercase text, longer than 5.");
}
// compact, but with utility method ('chain' in this case)
if (chain(StringUtils::isAllLowerCase).and(s -> s.length() < 5).test("test")) {
System.out.println("'test' is a lowercase text, shorter than 5.");
}
}
public static <T> Predicate<T> chain(Predicate<T> test) {
return test;
}
}
在这种情况下,2 个字符串 Predicate 链接成一个新的 Predicate。当您至少有一个句柄(即变量)来调用链接方法(在本例中为“and”)时,这会很好地工作。但是,如果要链接的表达式表示为 lambda 或方法引用,则需要将其中之一显式转换为变量,这会非常冗长。当编译器无法确定确切的类型时,你不得不求助于这种构造。但在大多数情况下,这只是我想避免的冗长开销。
在这个例子中,我自己编写了实用方法'chain'。 但是我可以为其他功能接口创建一个 (Function, Consumer, Supplier, BiConsumer, ...) 以及。
我不想使用这些方法创建我自己的实用程序 class(我可能会将其复制粘贴到我从事的每个项目),我想知道这样的 class 是否存在于JDK 还是在某个图书馆?
另一方面,如果这样的 class 不存在并且我不应该自己创建一个,我想听听为什么。
创建 Predicate
个实例以在后续 if
语句中使用它们是没有意义的。
Predicate
实例通常用于将条件传递给方法。在这种情况下,您可以研究特定的 API 以了解是否可以使用自然结构进行这种链接。
例如将 Predicate
传递给流时,您可以简单地进行两次或更多次 filter
调用:
stringStream.filter(StringUtils::isAllUpperCase).filter(s->s.length()>5). …
(您可以类似地使用多个 map
调用来链接 Function
s)
和其他API可能有类似的方法。
但毕竟,如果您有两个要合并的条件,并且都不是 Predicate
实例,那么直接的解决方案就是合并表达式:
stringStream.filter(s -> isAllUpperCase(s) && s.length()>5). …
或作为独立创作:
Predicate<String> allUpperCaseAndLongerThan5 = s -> isAllUpperCase(s) && s.length()>5;
请注意,您可以在此处使用 static import
作为实用方法,这样可以使用更紧凑的表达式。
使用Predicate.and
和Predicate.or
仅当您已经有一个Predicate
实例并想扩充其逻辑时才有用。但在这种情况下,您还有一个实例,您可以在该实例上毫无问题地调用 and
或 or
。