这是使用 Java 的 Optional.flatMap()
的一个有趣的困境。我有一个封装 CURIE 的类形式为"foo:bar"
或者只是 "bar"
。我还有一个用于将前缀注册到命名空间以及跟踪默认命名空间的类。它有一个方法findNamespaceByPrefix()
返回 Optional<URI>
(因为前缀可能未注册)和方法 getDefaultNamespace()
,还返回 Optional<URI>
(因为可能没有默认 namespace )。
鉴于一些 CURIE,我想找到 namespace 。使用这个很诱人:
Optional<URI> namespace = curie.getPrefix()
.flatMap(this::findNamespaceByPrefix)
.or(this::getDefaultNamespace);
但这是错误的。问题是它返回默认 namespace ,即使有前缀但没有 namespace 与该前缀关联。如果 CURIE 中根本没有指示任何前缀,我们只想取回默认 namespace (如果有)。
这是一个解决方案:
Optional<String> prefix = curie.getPrefix();
Optional<URI> namespace = prefix.isPresent()
? prefix.flatMap(this::findNamespaceByPrefix)
: getDefaultNamespace();
我对此很满意,但我觉得它使用三元运算符并使用 Optional.isPresent()
有点不起作用。通常表明有更好的方法来做事。
做任何Optional
专家们有更好、更实用的解决方案来“短路”平面映射吗? (我有预感,我可以在管道中使用 Optional
和 Optional:of
进行多层包装和展开 Optional:get
,但有没有更优雅的东西?)
最佳答案
您应该保留第二级可选,而不是“flatMapping”:
Optional<URI> namespace = curie.getPrefix()
.map(Application::findNamespaceByPrefix)
.orElseGet(Application::getDefaultNamespace);
map
操作将前缀(如果存在)映射到包装的 Optional<Optional<URI>>
中它要么为空(如果前缀不存在),要么包含 Optional<URI>
它要么是空的(如果找不到前缀的命名空间),要么包含实际的命名空间。
还有外部orElseGet
仅当包装 Optional
时才会被调用为空,因此您的前缀不存在。
关于java - 短路 JavaOptional.flatMap(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58839663/