[英]Lambda expressions with external immutable variables used within the expression
I have this example code that I've written specifically for this question, but it reflects a real scenario I was confronted with at work: 我有这个代码,我是专门针对这个问题编写的,但它反映了我在工作中遇到的真实场景:
List<String> names = Arrays.asList("ALICE", "Alice", "BOB", "Bob", "CHUCK", "Chuck");
Predicate<String> has_u_or_i_whenLowercased = Stream.of("u", "i")
.map(bit -> (Predicate<String>) (source -> source.toLowerCase(Locale.ENGLISH).contains(bit)))
.reduce(Predicate::or)
.orElse(p -> false);
List<String> english = names.stream()
.filter(has_u_or_i_whenLowercased)
.collect(Collectors.toList());
System.out.println(english);
System.out.println(english.size());
It creates a predicate that checks if the source String contains u
or i
when lowercased with the English locale ( EDIT: There are a dozen better and simpler ways to implement this, but this is just an example. In the real scenario I am filtering a small data set based on an arbitrary number of search criteria ). 它创建了一个谓词,用于检查源字符串是否包含
u
或i
当使用英语语言环境进行小写时( 编辑: 有十几个更好,更简单的方法来实现它,但这只是一个例子。在真实场景中我过滤了一个基于任意数量的搜索标准的小数据集 )。 I'm going to use this lambda expression across several methods of a class. 我将在类的几个方法中使用这个lambda表达式。
Now, assume I want to have a different locale, which will be passed as an argument to the method that will use the lambda expression (not the constructor). 现在,假设我想要一个不同的语言环境,它将作为参数传递给将使用lambda表达式(而不是构造函数)的方法。 At work, it's not a Locale I have to deal with, but I defined its boundary as being an immutable variable.
在工作中,它不是我必须处理的Locale,但我将其边界定义为不可变变量。
The simplest solution I could think of was to have a method "build" that lambda expression. 我能想到的最简单的解决方案是使用一个方法“构建”lambda表达式。
@Override
public void run() {
List<String> names = Arrays.asList("ALICE", "Alice", "BOB", "Bob", "CHUCK", "Chuck");
List<String> english = names.stream()
.filter(createUIPredicate(Locale.ENGLISH))
.collect(Collectors.toList());
System.out.println(english);
System.out.println(english.size());
System.out.println("--");
List<String> turkish = names.stream()
.filter(createUIPredicate(new Locale("tr", "TR")))
.collect(Collectors.toList());
System.out.println(turkish);
System.out.println(turkish.size());
}
private Predicate<String> createUIPredicate(Locale locale) {
return Stream.of("u", "i")
.map(bit -> (Predicate<String>) (source -> source.toLowerCase(locale).contains(bit)))
.reduce(Predicate::or)
.orElse(p -> false);
}
However I feel like there is something wrong with this approach. 但是我觉得这种方法有问题。 If I am injecting an external immutable variable into a functional interface, I thought maybe I'm supposed to pass it as an lambda expression argument instead somewhere?
如果我将一个外部不可变变量注入一个函数接口,我想也许我应该把它作为一个lambda表达式参数传递给某个地方?
When confronted with a lambda expression which has an external immutable variable used within the expression, and that immutable variable may be different for every use within a stream intermediate operation, is there a specific approach that matches a known functional programming pattern? 当面对一个lambda表达式,该表达式在表达式中使用了外部不可变变量,并且对于流中间操作中的每次使用,该不可变变量可能不同,是否有一种与已知函数编程模式匹配的特定方法?
There's not really much practical difference between your method solution and your lambda solution from the comments, both take advantage of lambdas "closing over" "effectively final" variables. 你的方法解决方案与评论中的lambda解决方案之间并没有太大的实际区别,它们都利用了lambda“关闭”“有效最终”变量。 Both are pretty common in the Java 8 functional code I've written.
在我编写的Java 8功能代码中,两者都很常见。
private Predicate<String> build(Locale locale) {
return str -> str.toLowerCase(locale);
}
versus: 与:
Function<Locale, Predicate<String>> build = locale -> str -> str.toLowerCase(locale);
The decision between the two is just one of style preference and/or whether that builder is used only within a single method or in multiple places in your class. 两者之间的决定只是样式首选项和/或该构建器是仅在单个方法中使用还是在类中的多个位置使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.