java 流和收集器,toMap()-两种方法?

q5lcpyga  于 2022-12-28  发布在  Java
关注(0)|答案(2)|浏览(140)

在下面两个代码片段中-哪一个更可取。

进近-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条目,然后使用getKeygetValue将其Map到toMap中,这有什么好处吗?或者更直接的approach 2也同样好吗?
随访问题:如果Iterable keys中的条目未排序,则合并函数(a, b) -> a是否为keys中的相同条目但顺序不同给出相同结果?

0x6upsns

0x6upsns1#

根据您提供的代码,两种方法将产生相同的结果。
后续问题:如果可迭代项keys中的条目未被排序,则合并函数(a, b) -> a可能根据条目被处理的顺序给予不同的结果。这是因为合并函数用于解决当两个元素被Map到同一key时的冲突,并且顺序可能影响在map中保留哪个元素。如果keys被排序,则合并函数将给予相同的结果

kognpnkq

kognpnkq2#

如果可迭代键或中的条目未排序,合并函数(a, b) -> a是否为键中的相同条目但顺序不同给出相同结果?
它与排序无关。

  • mergeFunction * 的行为是否确定取决于源是否是ordered(ordered仅仅意味着迭代的可预测顺序,元素可能无论如何都不会排序)。如果是这种情况,从给定的Iterable生成的Spliterator将具有特征Spliterator.ORDERED

这将指示所得到的流是 * 有序的 * 还是 * 无序的 *。
例如,HashSet没有特定的迭代顺序,与ArrayListArrayDeque等集合相反,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 * 的用例是当您需要TreeMapEnumMap或任何其他 * 特殊用途 * 实现时。

相关问题