Java 8:遍历Map的所有元素

时间:2018-07-19 15:33:11

标签: java-8 hashmap

我有一个validate方法,该方法返回一个boolean

我正在按以下方式调用此方法(Java 7):

    boolean isValid = true;
    for (String key: aMap.keySet()) {
        isValid &= validate(key, aMap.get(key));
    }

我想用Java 8重写此代码。

Java 8允许使用以下方法遍历Map:

aMap.forEach((k,v) -> validate(k, v));

但这不起作用:

aMap.forEach((k,v) -> isValid &= validate(k, v)); 

问题

如何将Java 7代码重写为Java 8以实现相同的结果?

注意:

我问了类似的问题here。这篇文章的不同之处在于,这次我想遍历Map的所有项目(使用validate方法来构建验证报告)。如果没有发生验证错误,isValid必须返回true;如果至少发生一个错误,则false必须返回。

2 个答案:

答案 0 :(得分:4)

您可以使用

boolean isValid = aMap.entrySet().stream()
    .map(e -> validate(e.getKey(), e.getValue()))
    .reduce(true, Boolean::logicalAnd);

因为与anyMatchallMatch等不同,Reduction不会发生短路。但是,您需要执行所有validate方法调用,这表明该方法内有副作用。重要的是要了解这些副作用必须是无干扰的,即这些方法的调用顺序无关紧要,甚至多个元素的并发求值也不应破坏它。

即使满足这些要求,也不鼓励在功能操作中产生此类副作用。例如,下一位查看您的代码的开发人员可能会说:“嘿,看来我们应该在这里使用allMatch”…

所以我会坚持下去。但是,在处理Map的关联时,您不应在entrySet()上循环以对每个键执行查找,而应使用

boolean isValid = true;
for(Map.Entry<String, ValueType> e: aMap.entrySet())
    isValid &= validate(e.getKey(), e.getValue());

从Java 10开始,您可以使用

boolean isValid = true;
for(var e: aMap.entrySet()) isValid &= validate(e.getKey(), e.getValue());

消除该循环中最令人讨厌的语法元素。

答案 1 :(得分:1)

aMap.forEach((k,v) -> isValid &= validate(k, v));的问题在于,在lambda表达式中捕获的变量应为finaleffectively final。这与Java中的anonymous inner classes相同。

因此,要回答您的查询,可以将isValid转换为final一个元素数组,如下所示:

final boolean[] isValid = {true};,然后
aMap.forEach((k,v) -> isValid[0] &= validate(k, v));

您也可以将其设置为atomic,但这将需要更多代码更改。这种解决方案要简单得多。