【问题标题】:Java 8: iterating across all elements of a MapJava 8:遍历 Map 的所有元素
【发布时间】:2018-07-19 15:33:11
【问题描述】:

我有一个返回booleanvalidate 方法。

我正在使用如下调用此方法(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

【问题讨论】:

    标签: java-8 hashmap


    【解决方案1】:

    你可以使用

    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());
    

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

    【讨论】:

    • 你说:“这些方法调用的顺序无关紧要,甚至多个元素的并发评估也不应该破坏它。”但是您编写的流不会像parallelStream() 那样并行运行。你能解释一下你的意思吗?
    • 嗯,是关于合同的。顺序流将按照源映射的迭代器传递它们的相同顺序调用方法,但这不是保证的属性。更糟糕的是,如果源地图一开始就没有定义的遭遇顺序,比如HashMap。我们可以在相同的情况下预测顺序调用顺序,但如果我们依赖顺序,它仍然是错误的代码。作为重击规则,使用 Stream API 的代码应该以将其转换为并行不会破坏它的方式编写,即使我们不使用它(还)。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 它绝对有效。它是一个原始的解决方案,尽管以阵列为代价。尽管如此,还是投了赞成票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    相关资源
    最近更新 更多