代码之家  ›  专栏  ›  技术社区  ›  Friedrich 'Fred' Clausen

从Java返回可选ifPresent()

  •  3
  • Friedrich 'Fred' Clausen  · 技术社区  · 6 年前

    我知道你不能从 ifPresent() 所以这个例子不起作用:

    public boolean checkSomethingIfPresent() {
        mightReturnAString().ifPresent((item) -> {
            if (item.equals("something")) {
                // Do some other stuff like use "something" in API calls
                return true; // Does not compile
            }
        });
        return false;
    }
    

    在哪里? mightReturnAString() 能够 返回有效字符串或空的可选字符串。我所做的是:

    public boolean checkSomethingIsPresent() {
        Optional<String> result = mightReturnAString();
    
        if (result.isPresent()) {
            String item = result.get();
            if (item.equals("something") {
                // Do some other stuff like use "something" in API calls
                return true;
            }
        }
        return false;
    }
    

    这比一开始只检查空值要长,感觉也没什么不同。我觉得必须有一个更简洁的方式使用任选。

    4 回复  |  直到 6 年前
        1
  •  1
  •   Naman    6 年前

    我想你要找的只是 filter 然后检查是否存在:

    return result.filter(a -> a.equals("something")).isPresent();
    
        2
  •  1
  •   shmosel    6 年前

    映射到布尔值怎么样?

    public boolean checkSomethingIfPresent() {
        return mightReturnAString().map(item -> {
            if (item.equals("something")) {
                // Do some other stuff like use "something" in API calls
                return true; // Does not compile
            }
            return false; // or null
        }).orElse(false);
    }
    
        3
  •  1
  •   Kartik    6 年前

    虽然@nullpointer和@Ravindra演示了如何将可选条件与另一个条件合并,但是您必须做更多的工作才能调用api并按照您在问题中的要求执行其他操作。以下内容在我看来是相当可读和简洁的:

    private static boolean checkSomethingIfPresent() {
        Optional<String> str = mightReturnAString();
        if (str.filter(s -> s.equals("something")).isPresent()) {
            //call APIs here using str.get()
            return true;
        }
        return false;
    }
    

    一个更好的设计是连锁方法:

    private static void checkSomethingIfPresent() {
        mightReturnFilteredString().ifPresent(s -> {
            //call APIs here
        });
    }
    
    private static Optional<String> mightReturnFilteredString() {
        return mightReturnAString().filter(s -> s.equals("something"));
    }
    
    private static Optional<String> mightReturnAString() {
        return Optional.of("something");
    }
    
        4
  •  0
  •   Anonymous    6 年前

    理想的解决方案是命令查询分离:创建一个方法(command)来处理字符串(如果存在的话)。还有另一个方法(查询)来告诉您它是否存在。

    然而,我们生活在一个不理想的世界,完美的解决方案是永远不可能的。如果在您的情况下,您不能将命令和查询分开,那么我喜欢shmosel已经提出的想法:映射到 boolean . 作为一个细节我会用 filter 而不是内心 if 声明:

    public boolean checkSomethingIfPresent() {
        return mightReturnAString().filter(item -> item.equals("something"))
                .map(item -> {
                    // Do some other stuff like use "something" in API calls
                    return true; // (compiles)
                })
                .orElse(false);
    }
    

    我不喜欢的是呼叫链有副作用,这通常是不期望的,除了 ifPresent ifPresentOrElse (和 orElseThrow ,当然)。

    如果我们坚持使用 如果现在 为了使副作用更清楚,这是可能的:

        AtomicBoolean result = new AtomicBoolean(false);
        mightReturnAString().filter(item -> item.equals("something"))
                .ifPresent(item -> {
                    // Do some other stuff like use "something" in API calls
                    result.set(true);
                });
        return result.get();
    

    我用 AtomicBoolean 作为结果的容器,因为不允许我们分配给基元 布尔型 从羔羊体内。我们不需要它的原子性,但它也不会造成伤害。

    链接: Command–query separation 论维基百科