短路Java可选。flatMap()

短路Java可选。flatMap(),java,optional,Java,Optional,使用Java的Optional.flatMap()有一个有趣的难题。我有一个类,它以“foo:bar”或“bar”的形式封装了。我还有一个类,用于向名称空间注册前缀,以及跟踪默认名称空间。它有一个方法findNamespaceByPrefix()返回一个可选的(因为前缀可能没有注册)和一个方法getDefaultNamespace(),也返回一个可选的(因为可能没有默认的命名空间) 给定一些居里数,我想找到名称空间。这很吸引人: Optional namespace=curie.getPrefi

使用Java的
Optional.flatMap()
有一个有趣的难题。我有一个类,它以
“foo:bar”
“bar”
的形式封装了。我还有一个类,用于向名称空间注册前缀,以及跟踪默认名称空间。它有一个方法
findNamespaceByPrefix()
返回一个
可选的
(因为前缀可能没有注册)和一个方法
getDefaultNamespace()
,也返回一个
可选的
(因为可能没有默认的命名空间)

给定一些居里数,我想找到名称空间。这很吸引人:

Optional namespace=curie.getPrefix()
.flatMap(this::findNamespaceByPrefix)
.或(此::getDefaultNamespace);
但这是错误的。问题是它返回默认名称空间,即使有前缀但没有与该前缀关联的名称空间。如果CURIE中没有任何前缀,我们只想返回默认名称空间(如果有)

以下是一个解决方案:

Optional prefix=curie.getPrefix();
可选名称空间=前缀.isPresent()
? prefix.flatMap(this::findNamespaceByPrefix)
:getDefaultNamespace();
我对此很满意,但我觉得使用三元运算符有点不起作用,并且使用
可选。isPresent()
通常表示有更好的方法来做事情

是否有
可选的
专家有更好、更实用的解决方案来“短路”平面映射?(我有一种预感,我可以通过使用
Optional:of
Optional:get
来完成几层包装和展开
Optional
,但是否有更优雅的东西?

你应该保留第二层可选:

Optional<URI> namespace = curie.getPrefix()
    .map(Application::findNamespaceByPrefix)
    .orElseGet(Application::getDefaultNamespace);
Optional namespace=curie.getPrefix()
.map(应用程序::findNamespaceByPrefix)
.OrelGet(应用程序::getDefaultNamespace);
map
操作将前缀(如果存在)映射到一个包装的
Optional
,该前缀为空(如果没有前缀),或包含一个空(如果找不到前缀的命名空间)或包含实际命名空间的
Optional


只有当包装
可选的
为空且您的前缀不存在时,才会调用外部
orElseGet

检查是否有空前缀

Optional<URI> namespace = prefix
   .filter(Objects::nonNull)
   .flatMap(this::findNamespaceByPrefix)
   .or(this::getDefaultNamespace);
可选名称空间=前缀
.filter(对象::非空)
.flatMap(this::findNamespaceByPrefix)
.或(此::getDefaultNamespace);
您可以按如下方式进行测试:

    public static void main(String[] args) {
        test(Optional.ofNullable(null));
        test(Optional.ofNullable("yourprefix"));
    }

    private static void test(Optional<String> prefix) {
        Optional<URI> namespace2 = prefix
                .filter(Objects::nonNull)
                .flatMap(p -> Optional.of(URI.create(p)))
                .or(() -> Optional.of(URI.create("default")));

        System.out.println(namespace2);
    }
publicstaticvoidmain(字符串[]args){
测试(可选的空值);
测试(可选。不可用(“您的前缀”);
}
专用静态无效测试(可选前缀){
可选名称空间2=前缀
.filter(对象::非空)
.flatMap(p->Optional.of(URI.create(p)))
.或(()->可选的(URI.create(“default”));
System.out.println(名称空间2);
}

是!就是这样!我有一种预感,我需要保留
可选的
,但我对如何摆脱它感到困惑。我想这就是解决办法!问题在于
flatMap()
将名称空间丢失的两个不同原因合并在一起。此解决方案将两者分开,不会混淆。在您的示例中,变量
前缀是什么类型的?它是
字符串类型的吗?它是
可选类型的吗?它是
类型吗?还是别的?@GarretWilson,它是
Optional prefix=Optional.ofNullable(“您的前缀或null,如果不存在”)
可选
不能包含
值时,如何通过
对象::非空
过滤
可选
值?对
可选的
执行这样的操作难道不是毫无意义的吗?@GarretWilson编译代码必须是
可选的
,与问题中相同。但是仍然没有解决这个问题,忽略那里的第一个代码块。不,
可选。空值(null)
将不包含
null
值。它将不包含任何值;它将是空的。如果您不相信我,请尝试调用
Optional.ofNullable(null.get()
)。