Java 流无干扰和副作用

查看 Java java.util.stream 包文档,对于在流使用中遵循的最佳实践产生了疑问。考虑到这段代码:


HashMap<Integer,Integer> map = new HashMap<>();

map.put(1,1);

map.put(2,2);

map.put(3,3);

map.put(4,4);

map.keySet().parallelStream().forEach(key -> {

        if (key == 3) { 

            map.put(3,0);

        }

});

  1. 代码输出是否总是等于 ([1,1],[2,2],[3,0],[4,4])?

  2. map.put(3,0) 可以被视为非干扰操作吗?

  3. map.put(3,0) 可以被视为可接受的副作用吗?

换句话说,上面的代码可以被认为符合流文档中建议的最佳实践吗?


慕的地10843
浏览 214回答 3
3回答

不负相思意

不不不。避免副作用。符合文档的示例代码:Map<Integer,Integer> updatedMap = map.keySet().parallelStream()&nbsp; &nbsp; &nbsp; &nbsp; .filter(e -> e == 3)&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toMap(Function.identity(), e -> 0));map.putAll(updatedMap);

梦里花落0921

您的示例绝对违反了非干扰要求:对于大多数数据源来说,防止干扰意味着确保数据源在流管道的执行过程中完全不被修改。一个显着的例外是其源是并发集合的流,这些流是专门为处理并发修改而设计的。您的数据源 aHashMap并非旨在处理并发修改,因此在流管道执行期间根本不应修改它。因此,您的第二和第三个问题的答案是否定的。至于第一个问题,您的特定代码可能仍会产生预期的结果,因为您的条件确保只有一个线程会调用map.put(3,0).&nbsp;但是,这仍然被认为是Streams的错误用法。

LEATH

比较(一)map.keySet().parallelStream().forEach(key -> {&nbsp; &nbsp; &nbsp; &nbsp; if (key == 3) {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put(3, 0);&nbsp; &nbsp; &nbsp; &nbsp; }});(添加了一个新条目)与 (b)map.entrySet().parallelStream().forEach(e -> {&nbsp; &nbsp; &nbsp; &nbsp; if (e.getKey() == 3) {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.setValue(0);&nbsp; &nbsp; &nbsp; &nbsp; }});(没有创建、移动 Entry 对象。但要注意LinkedHashMap.)(a) 不安全(b) 安全代码输出是否总是等于 ([1,1],[2,2],[3,0],[4,4])?(a) 否 (b) 是可以map.put(3, 0)认为是非干扰操作吗?(a) 否 (b)setValue(0)是可以map.put(3, 0)认为是可以接受的副作用吗?(a) 否 (b)setValue(0)是所以(a)是邪恶的,(b)是好的。为什么要提到 entrySet.setValue?实际上&nbsp;HashMap.put在 Oracle实现中可能与Entry.setValue.&nbsp;这将需要使用实现知识 - 丑陋。而 Entry.setValue 基于原始地图的支持,人们可能会推断出只有 value 字段被覆盖。请注意, aLinkedHashMap需要对条目重新排序,而重新排序又是不安全的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java