假设我有一个货币汇率加载器,仅当所有汇率加载成功时才返回
isLoaded=true
结果:
//List<String> listFrom = Stream.of("EUR", "RUB").collect(toList());
//List<String> listTo = Stream.of("EUR", "CNY").collect(toList());
boolean isLoaded = true;
final FixerDataProvider httpProvider = new FixerDataProvider(maxAttempts);
final List<CurrencyRatePair> data =
listFrom.stream()
.flatMap(from -> {
final List<CurrencyRatePair> result = httpProvider.findRatesBetweenCurrencies(from, listTo);
if (Objects.isNull(result) || result.size() == 0) {
isLoaded = false; //!!!Not working as ineffectively final!!!
}
return result.stream();
}).collect(Collectors.toList());
if (!isLoaded) {
return false;
}
// do smth with loaded data
return true;
当 isLoaded = false;
变量不是最终变量或实际上最终变量时,不允许在 lambda 函数内进行
isLoaded
赋值。
在 lambda 表达式中设置/删除布尔标志的最优雅的解决方案是什么?
您认为 AtomicBoolean 和 set(false) 方法作为一种可能的方法怎么样?
为了让这个带有副作用的特定 lambda 发挥作用,将
isLoaded
变成
AtomicBoolean
可能是你最好的选择。您可以通过将
isLoaded
设为大小为 1 的
boolean[]
来实现相同的效果,但这对我来说似乎不如使用
AtomicBoolean
优雅。但是说真的,也可以尝试使用老式循环,看看你更喜欢哪一个。
并行流,则必须使用AtomicBoolean
。因为
boolean[1]
在
parallel
场景下可能不是线程安全的。
java.util.stream javadoc 指出
一般来说,不鼓励流操作的行为参数产生副作用,因为它们通常会导致无意中违反无状态性要求,以及其他线程安全隐患。也就是说,如果您无论如何都想这样做,您使用 AtomicBoolean 确定的解决方案就可以很好地完成任务。
您可以针对您的情况使用 AtomicReference,这是来自
ConditionEvaluationListenerJava8Test 的类似片段
public void expectedMatchMessageForAssertionConditionsWhenUsingLambdasWithoutAlias() {
final AtomicReference<String> lastMatchMessage = new AtomicReference<>();
CountDown countDown = new CountDown(10);
with()
.conditionEvaluationListener(condition -> {
try {
countDown.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
lastMatchMessage.set(condition.getDescription());
})
.until(() -> assertEquals(5, (int) countDown.get()));
String expectedMatchMessage = String.format("%s reached its end value", CountDown.class.getName());
assertThat(lastMatchMessage.get(), allOf(startsWith("Condition defined as a lambda expression"), endsWith(expectedMatchMessage)));
}
干杯!
isLoaded=false
列表均为空的情况下,您才会得到
result
(如果
result
列表为空,您将在下一行中得到NPE,因此没有任何理由进行空检查这样)。在这种情况下,您的
data
列表也将为空,并且您不需要任何布尔标志,只需检查是否
data.isEmpty()
并返回 false 如果
true
。