哪个是在lambda函数中设置/删除布尔标志的最佳方法

时间:2017-10-12 15:47:58

标签: java lambda

假设我的货币汇率加载程序仅在成功加载所有汇率时返回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)方法?

4 个答案:

答案 0 :(得分:8)

正如其他人所建议的那样,你可能会对旧式循环感觉更好。编写带有副作用的lambdas确实感觉有点像编程失误,但你可能会发现同样数量的开发人员认为它也很好。

至于让这种特殊的lambda-with-side效果起作用,将isLoaded变成AtomicBoolean可能是你最好的选择。通过将isLoaded设为boolean[]大小为1,您可以达到相同的效果,但这似乎不如向AtomicBoolean提供给我。

但严重的是,尝试使用旧式循环,看看你更喜欢哪一个。

答案 1 :(得分:2)

java.util.stream javadoc表示

  

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

也就是说,如果你想要这样做,你用AtomicBoolean识别的解决方案就可以了。

答案 2 :(得分:2)

匿名内部类和lambda表达式中使用的变量必须是最终的。

您可以在案例中使用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))); 
} 

干杯!

答案 3 :(得分:0)

如果我理解你,只有在所有关闭isLoaded=false列表为空的情况下才会获得result(如果result列表为空,您将在下一行获得NPE,以便没有任何理由以这种方式进行空检查)。在这种情况下,您的data列表也将为空,并且您不需要任何布尔标记,只需检查是否data.isEmpty()并在true时返回false。