在下面两个代码片段中-哪一个更可取。
进近-1
public Map<String, List<MyObj>> approach1(
Iterable<? extends String> keys) {
return StreamSupport.stream(keys.spliterator(), false)
.map(dt -> new AbstractMap.SimpleEntry<>(dt, load(dt)))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, HashMap::new));
}
进近-2
public Map<String, List<MyObj>> approach2(
Iterable<? extends String> keys) {
return StreamSupport.stream(keys.spliterator(), false)
.collect(toMap(dt -> dt, k -> load(dt), (a, b) -> a, HashMap::new));
}
在approach 1中,显式创建了一个Map条目,然后使用getKey
和getValue
将其Map到toMap
中,这有什么好处吗?或者更直接的approach 2也同样好吗?
随访问题:如果Iterable keys
中的条目未排序,则合并函数(a, b) -> a
是否为keys
中的相同条目但顺序不同给出相同结果?
2条答案
按热度按时间0x6upsns1#
根据您提供的代码,两种方法将产生相同的结果。
后续问题:如果可迭代项
keys
中的条目未被排序,则合并函数(a, b) -> a
可能根据条目被处理的顺序给予不同的结果。这是因为合并函数用于解决当两个元素被Map到同一key
时的冲突,并且顺序可能影响在map
中保留哪个元素。如果keys
被排序,则合并函数将给予相同的结果kognpnkq2#
如果可迭代键或中的条目未排序,合并函数
(a, b) -> a
是否为键中的相同条目但顺序不同给出相同结果?它与排序无关。
Iterable
生成的Spliterator
将具有特征Spliterator.ORDERED
。这将指示所得到的流是 * 有序的 * 还是 * 无序的 *。
例如,
HashSet
没有特定的迭代顺序,与ArrayList
、ArrayDeque
等集合相反,HashSet
保证确定的迭代顺序。***注意:*Stream API提供的某些方法可以更改管道的排序。操作 *
unordered()
* 将放松排序约束(如果流已排序),而 *sorted()
* 将强制排序。根据
toMap()
的文档:mergeFunction-一个合并函数,用于解决与相同键关联的值之间的冲突,如提供给
Map.merge(Object, Object, BiFunction)
的因此在有序流中,* mergeFunction *
(a, b) -> a
将保留从流中较早出现的流元素生成的值。但是如果流是无序的,元素可以由收集器以任何顺序使用,并且不可能预测哪个值将最终出现在结果Map中。关于这两条河流之间的差异问题,请参见Map第一个代码片段中的()操作是多余的,因为它只创建了不必要的中间
Map.Entry
示例。看起来您添加此操作只是为了能够在收集器中应用方法引用,这是不合理的。对象创建不是免费的,代码的读者可能不太清楚为什么需要这个中间转换。另外,注意在两个代码段中的收集器内指定 * mapFactory *
HashMap::new
是没有意义的,因为默认情况下,将为您提供Map
接口的通用实现,其格式为HashMap
或将来可能作为其推荐替代品出现的格式。因此,如果您"我们可以获得HashMap
作为流执行的结果。toMap
的 * four-args * 版本需要 * mapFactory * 的用例是当您需要TreeMap
、EnumMap
或任何其他 * 特殊用途 * 实现时。