Java 8 Java8:遍历映射的所有元素

Java 8 Java8:遍历映射的所有元素,java-8,hashmap,Java 8,Hashmap,我有一个validate方法,它返回一个布尔值 我使用以下方法调用此方法(Java 7): boolean isValid = true; for (String key: aMap.keySet()) { isValid &= validate(key, aMap.get(key)); } 我想用Java8重写这段代码 Java 8允许使用以下各项在地图上进行迭代: aMap.forEach((k,v) -> validate(k, v)

我有一个
validate
方法,它返回一个
布尔值

我使用以下方法调用此方法(Java 7):

    boolean isValid = true;
    for (String key: aMap.keySet()) {
        isValid &= validate(key, aMap.get(key));
    }
我想用Java8重写这段代码

Java 8允许使用以下各项在地图上进行迭代:

aMap.forEach((k,v) -> validate(k, v));
但这是行不通的:

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

如何将Java 7代码重写为Java 8以获得相同的结果

注:


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

aMap.forEach((k,v)->isValid&=validate(k,v))的问题是指lambda表达式中捕获的变量应为
final
有效final
。Java中的
匿名内部类
也是如此

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

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


您也可以将其原子化,但这需要更多的代码更改。这个解决方案要简单得多。

aMap.forEach((k,v)->的问题是有效的&=validate(k,v))
是指lambda表达式中捕获的变量应为
final
有效final
。Java中的
匿名内部类
也是如此

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

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

您也可以将其原子化,但这需要更多的代码更改。此解决方案简单得多。

您可以使用

boolean isValid = aMap.entrySet().stream()
    .map(e -> validate(e.getKey(), e.getValue()))
    .reduce(true, Boolean::logicalAnd);
anyMatch
allMatch
等不同,reduce不知道短路。但是,执行所有
validate
方法调用的要求表明该方法存在副作用。理解这些副作用必须是无干扰的,这一点很重要,也就是说,这些方法调用的顺序并不重要,甚至多个元素的并发评估也不应该破坏它

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

所以我会留在圈里。但是,在处理
映射的关联时,不应在
entrySet()
上循环以对每个键执行查找,而应使用

boolean isValid = true;
for(Map.Entry<String, ValueType> e: aMap.entrySet())
    isValid &= validate(e.getKey(), e.getValue());
消除循环中最烦人的语法元素。

您可以使用

boolean isValid = aMap.entrySet().stream()
    .map(e -> validate(e.getKey(), e.getValue()))
    .reduce(true, Boolean::logicalAnd);
anyMatch
allMatch
等不同,reduce不知道短路。但是,执行所有
validate
方法调用的要求表明该方法存在副作用。理解这些副作用必须是无干扰的,这一点很重要,也就是说,这些方法调用的顺序并不重要,甚至多个元素的并发评估也不应该破坏它

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

所以我会留在圈里。但是,在处理
映射的关联时,不应在
entrySet()
上循环以对每个键执行查找,而应使用

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

消除该循环中最烦人的语法元素。

您说:“这些方法调用的顺序应该无关紧要,甚至多个元素的并发计算也不应该破坏它。”但您编写的流不会像
parallelStream()
那样并行运行。你能解释一下你的意思吗?嗯,是关于合同的。顺序流将以源映射的迭代器交付方法的相同顺序调用该方法,但这不是一个保证的属性。更糟糕的是,如果源地图一开始没有定义遭遇顺序,比如
HashMap
。在相同的情况下,我们可以预测顺序调用顺序,但如果依赖顺序,代码仍然是错误的。作为重击的规则,使用流API的代码应该以这样的方式编写:即使我们还没有使用它,将其转换为并行也不会破坏它。你说:“这些方法调用的顺序不重要,甚至多个元素的并发计算也不应该破坏它。”但是您编写的流不会像
parallelStream()
那样并行运行。你能解释一下你的意思吗?嗯,是关于合同的。顺序流将以源映射的迭代器交付方法的相同顺序调用该方法,但这不是一个保证的属性。更糟糕的是,如果源地图一开始没有定义遭遇顺序,比如
HashMap
。在相同的情况下,我们可以预测顺序调用顺序,但如果依赖顺序,代码仍然是错误的。作为thump的规则,使用streamapi的代码应该以这样的方式编写:即使我们还没有使用它,将它转换为并行也不会破坏它。它肯定能工作。这是一个原创的解决方案,尽管以阵列为代价。尽管如此,还是投了赞成票,谢谢。这确实有效。这是一个原创的解决方案,尽管以阵列为代价。