这是在 lambda 函数内设置/删除布尔标志的最佳方法

问题描述 投票:0回答:4

假设我有一个货币汇率加载器,仅当所有汇率加载成功时才返回

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) 方法作为一种可能的方法怎么样?

java lambda
4个回答
20
投票
正如其他人建议的那样,使用旧式循环可能会更好。编写带有副作用的 lambda 确实感觉有点编程失礼,但您可能会发现同样数量的开发人员认为这也很好。

为了让这个带有副作用的特定 lambda 发挥作用,将

isLoaded

 变成 
AtomicBoolean
 可能是你最好的选择。您可以通过将 
isLoaded
 设为大小为 1 的 
boolean[]
 来实现相同的效果,但这对我来说似乎不如使用 
AtomicBoolean
 优雅。

但是说真的,也可以尝试使用老式循环,看看你更喜欢哪一个。


如果使用

并行流,则必须使用AtomicBoolean

。因为 
boolean[1]
parallel
 场景下可能不是线程安全的。


3
投票

java.util.stream javadoc 指出

一般来说,不鼓励流操作的行为参数产生副作用,因为它们通常会导致无意中违反无状态性要求,以及其他线程安全隐患。

也就是说,如果您无论如何都想这样做,您使用 AtomicBoolean 确定的解决方案就可以很好地完成任务。


2
投票
匿名内部类和 lambda 表达式中使用的变量必须是有效的 Final。

您可以针对您的情况使用 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))); }

干杯!


0
投票
如果我正确理解,只有在所有关闭的

isLoaded=false

列表均为空的情况下,您才会得到
result
(如果
result
列表为空,您将在下一行中得到NPE,因此没有任何理由进行空检查这样)。在这种情况下,您的 
data
 列表也将为空,并且您不需要任何布尔标志,只需检查是否 
data.isEmpty()
 并返回 false 如果 
true

© www.soinside.com 2019 - 2024. All rights reserved.