为什么我不能使用过滤器作为流中的最后一步

我不断被告知不通过诸如collect和findFirst之类的方法终止Stream是不好的做法,但没有真正的反馈说明为什么在博客中没有太多谈论它。


看下面的示例,我没有使用大量嵌套的 if 检查,而是使用Optional 来获取列表值。如您所见,我的最后一步是在该流中进行过滤。这对我来说按预期工作,即取回列表。为什么这是错误的,我应该如何写呢?


import lombok.Getter;

import lombok.Setter;

import java.util.*;


public class Main {

    public static void main(String[] args) {


        RequestBean requestBean = new RequestBean();

        // if I uncomment this I will get the list values printed as expected

//        FruitBean fruitBean = new FruitBean();

//        AnotherBean anotherBean = new AnotherBean();

//        InnerBean innerBean = new InnerBean();

//        requestBean.setFruitBeans(Collections.singletonList(fruitBean));

//        fruitBean.setAnotherBeans(Collections.singletonList(anotherBean));

//        anotherBean.setInnerBeans(Collections.singletonList(innerBean));

//        List<String> beans = Arrays.asList("apple", "orange");

//        innerBean.setBeans(beans);


        List<String> result = getBeanViaOptional(requestBean);


        if(result != null){

            for(String s : result){

                System.out.println(s);

            }

        }else {

            System.out.println("nothing in list");

        }


    }


    private static List<String> getBeanViaOptional(RequestBean bean){

        Optional<List<String>> output = Optional.ofNullable(bean)

                .map(RequestBean::getFruitBeans)

                .map(n -> n.get(0))

                .map(FruitBean::getAnotherBeans)

                .map(n -> n.get(0))

                .map(AnotherBean::getInnerBeans)

                .map(n -> n.get(0))

                .map(InnerBean::getBeans)

                // why is this bad practice to end with a filter. how should I write this then?

                .filter(n -> n.contains("apple"));


        if(!output.isPresent()){

            throw new CustomException();

        }


        return output.get();

    }



MMMHUHU
浏览 123回答 2
2回答

弑天下

我不断被告知不通过诸如collect和findFirst之类的方法终止Stream是不好的做法,但没有真正的反馈说明为什么在博客中没有太多谈论它。这实际上取决于上下文,如果您说“我可以用中间操作结束流,例如filter而不调用终端操作(消耗流的操作) ”那么是的,这是不好的做法并且毫无意义,因为您只是定义了一些标准,但从未要求“结果”。流是惰性的,因为它们不会执行任何操作,除非终端操作(例如 等)告知这样collect做findFirst。如果您说“从方法返回流是一种不好的做法吗”,那么可能值得阅读有关是否应该返回流或集合的答案。此外,请注意您的getBeanViaOptional逻辑是在Optional<T>a 而不是上运行的Stream<T>。是的,它们都有map,flatMap但filter请注意, anOptional<T>只能包含一个值或者为空,而流可以包含一个或多个值。您使用Optional而不是命令式的方法if在可读性、维护等方面显然更好。所以我建议您继续使用这种方法,尽管您可以使用orElseThrowie 来改进它:return Optional.ofNullable(bean)                .map(RequestBean::getFruitBeans)                .map(n -> n.get(0))                .map(FruitBean::getAnotherBeans)                .map(n -> n.get(0))                .map(AnotherBean::getInnerBeans)                .map(n -> n.get(0))                .map(InnerBean::getBeans)                .filter(n -> n.contains("apple"))                .orElseThrow(CustomException::new);

温温酱

对于流,当没有终端操作时,通常不会执行任何中间操作。您的示例使用Optional.&nbsp;它的操作map和filter流中的一些中间操作同名,但又不同。您的示例在您的问题所询问的行上是可以的(不错的做法)。另一件事是(正如 Aomine 已经指出的那样).orElseThrow是获取 中的值Optional并在没有值时抛出异常的更短方法。更重要的是使用起来更安全.orElseThrow&nbsp;(或者.orElse如果有默认值)。Optional.get()应尽可能避免。NoSuchElementException如果没有值,您将得到 a 。NullPointerException这几乎和不使用时得到 a 一样糟糕Optional。Optional以正确的方式使用可以保护您免受NullPointerException.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java