有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

短接Java可选。flatMap()

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

给定一些居里数,我想找到名称空间。使用这个很有诱惑力:

Optional<URI> namespace = curie.getPrefix()
    .flatMap(this::findNamespaceByPrefix)
    .or(this::getDefaultNamespace);

但这是错误的。问题是,它返回默认名称空间,即使有前缀,但没有与该前缀关联的名称空间。如果居里表中没有任何前缀,我们只想返回默认名称空间(如果有)

以下是一个解决方案:

Optional<String> prefix = curie.getPrefix();
Optional<URI> namespace = prefix.isPresent()
    ? prefix.flatMap(this::findNamespaceByPrefix)
    : getDefaultNamespace();

我对此很满意,但我觉得使用三元运算符有点不实用,使用Optional.isPresent()通常表明有更好的方法

有没有任何专家有更好、更实用的解决方案来“短路”平面映射?(我有一种预感,我可以用管道中的Optional:ofOptional:get用几层包装和拆开Optional来做一些事情,但是有没有更优雅的东西呢?)


共 (2) 个答案

  1. # 1 楼答案

    检查空前缀

    Optional<URI> namespace = prefix
       .filter(Objects::nonNull)
       .flatMap(this::findNamespaceByPrefix)
       .or(this::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);
        }
    
  2. # 2 楼答案

    与“flatMapping”不同,您应该保留第二级可选:

    Optional<URI> namespace = curie.getPrefix()
        .map(Application::findNamespaceByPrefix)
        .orElseGet(Application::getDefaultNamespace);
    

    map操作将前缀(如果存在)映射到一个包装的Optional<Optional<URI>>中,该前缀要么为空(如果没有前缀),要么包含一个空的Optional<URI>(如果找不到前缀的名称空间),要么包含实际的名称空间

    外部orElseGet只有在包装Optional为空且前缀不存在时才会被调用