gpt4 book ai didi

java - 有没有一种优雅的方法可以将 Map> 转换为稀疏 Map

转载 作者:IT老高 更新时间:2023-10-28 20:59:52 27 4
gpt4 key购买 nike

有没有一种优雅的方法来转换 Map<P, Optional<Q>>到稀疏 Map<P, Q> ?

这应该可行,但有点笨拙:

Map<P,Optional<Q>> map = ...;
Map<P,Q> map2 = map.entrySet()
.stream().filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(e -> e.getKey(), e->e.getValue().get()));

最佳答案

我想说你的方式几乎已经是最优雅的方式了,我只会做一些轻微的外观改动,并用 Entry 替换你的收集器中的 e -> e.getKey()::getKey。这只是一个很小的变化,但比其他 lambda 更好地传达您的 意图

Map<P, Optional<Q>> map = new HashMap<>();
Map<P, Q> sparseMap = map.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(Entry::getKey, e -> e.getValue().get()));

为什么其他解决方案没有更好/更优雅?

因为它们不是更简洁,而且它们再次陷入了不声明 what 你想做什么,而是 how 的陷阱,这在程序样式中很常见,但在功能性方面则不然。

如果你看一下上面的代码,它几乎是不言自明的,并且有一个很好的流程。你首先有一个带有 Optionals 的非稀疏映射,然后声明没有 Optionals 的稀疏映射,然后描述从前者映射到后者的转换。这也没有副作用。只有在收集器实际完成时才分配稀疏映射。

如果您查看其他解决方案,那些反转逻辑流程并使用程序思维方式的解决方案:

Map<P, Optional<Q>> map = [....];
Map<P, Q> sparseMap = new HashMap<>();
map.forEach((key, opt) -> opt.ifPresent(value -> sparseMap.put(key, value)));

这只是稍微短了一点:

Map<P, Optional<Q>> map = [....];
Map<P, Q> sparseMap = new HashMap<>();
for (Entry<P, Optional<Q>> e : map.entrySet()) e.getValue().ifPresent(value -> sparseMap.put(key, value))

由于类型推断,您节省了一些字符,但最后,如果您合理地格式化它们,两种 foreach 解决方案都需要 4 个 LOC,因此它们不会比功能性的更短。他们也不清楚。 相反,它们依赖于在另一张 map 中造成副作用。这意味着在计算过程中,您会得到一个分配给变量的部分构造的稀疏映射。使用功能解决方案,只有在正确构建 map 时才会分配 map 。这只是一个小问题,在这种情况下可能不会引起问题,但对于可能变得相关的其他情况(例如涉及并发时),特别是当另一个 map 不是局部变量,而是一个字段——或者更糟的是,从其他地方传入。

此外,函数式方法的扩展性更好 - 如果您有大量数据,切换到并行流是微不足道的,将 foreach 方法转换为并行需要重写函数式 filter/collect 方法。这与此类轻量级操作无关(实际上,不要在这里这样做,它可能会更慢),但在其他情况下可能是理想的特性。

在我看来,使用函数式 filter/collect 方法比使用过程式 foreach 方法更可取,因为你训练自己使用好的习惯。但请记住,“优雅”往往在旁观者的眼中。对我来说,更“优雅”的方式是没有副作用的正确功能方式。 YMMV。

关于java - 有没有一种优雅的方法可以将 Map<P, Optional<Q>> 转换为稀疏 Map<P, Q>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54747656/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com