Map<RiskFactor,RiskFactorChannelData> updateMap = updates.stream().filter(this::updatedValueIsNotNull). // Remove null updated values collect(Collectors.toMap( u -> u.getUpdatedValue().getKey(),// then merge into a map of key->value. Update::getUpdatedValue,(a,b) -> b)); // If two values have the same key then take the second value
具体来说,我想从列表中取出值并将它们放入地图中.这一切都很完美.我关心的是订购.
例如,如果列表具有:
a1,b1,a2
如何确保最终地图包含:
a->a2 b->b1
代替
a->a1 b->b1
传入列表是有序的,stream().filter()应该保持顺序但我在Collectors.toMap的文档中看不到有关输入顺序的任何内容.
在一般情况下这是安全的还是我到目前为止我的测试案例幸运?我是否会依赖JVM并且面临未来变化的风险?
如果我只是编写一个for循环,这很容易保证,但潜在的流行为的“模糊性”让我很担心.
我不打算为此使用并行,我纯粹是想要了解到达toMap的顺序非并行流的行为.
解决方法
Its documentation引用Map.merge来解释合并函数的语义,但不幸的是,文档也有点薄.它没有提到使用(oldValue,newValue)显式调用此函数的事实;它只能从代码示例中推断出来.
toMap
’s documentation进一步指出:
The returned
Collector
is not concurrent. For parallel stream pipelines,thecombiner
function operates by merging the keys from one map into another,which can be an expensive operation. If it is not required that results are merged into theMap
in encounter order,usingtoConcurrentMap(Function,Function,BinaryOperator,Supplier)
may offer better parallel performance.
因此,如果不需要遇到订单,它会明确指向不同的收集器.通常,Collectors
提供的所有内置收集器只有在明确说明时才是无序的,这只是“… Concurrent …”收集器和toSet()收集器的情况.