为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

MMMHUHU 2023-08-16 10:49:16
我不断被告知不通过诸如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();    }
查看完整描述

2 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

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

这实际上取决于上下文如果您说“我可以用中间操作结束流,例如filter而不调用终端操作(消耗流的操作) ”那么是的,这是不好的做法并且毫无意义,因为您只是定义了一些标准,但从未要求“结果”。

流是惰性的,因为它们不会执行任何操作,除非终端操作(例如 等)告知这样collectfindFirst

如果您说“从方法返回流是一种不好的做法吗”,那么可能值得阅读有关是否应该返回流或集合的答案。

此外,请注意您的getBeanViaOptional逻辑是在Optional<T>a 而不是上运行的Stream<T>。是的,它们都有mapflatMapfilter请注意, 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);


查看完整回答
反对 回复 2023-08-16
?
温温酱

TA贡献1752条经验 获得超4个赞

对于流,当没有终端操作时,通常不会执行任何中间操作。您的示例使用Optional. 它的操作mapfilter流中的一些中间操作同名,但又不同。您的示例在您的问题所询问的行上是可以的(不错的做法)。

另一件事是(正如 Aomine 已经指出的那样).orElseThrow是获取 中的值Optional并在没有值时抛出异常的更短方法。更重要的是使用起来更安全.orElseThrow (或者.orElse如果有默认值)。Optional.get()应尽可能避免。NoSuchElementException如果没有值,您将得到 a 。NullPointerException这几乎和不使用时得到 a 一样糟糕OptionalOptional以正确的方式使用可以保护您免受NullPointerException.


查看完整回答
反对 回复 2023-08-16
  • 2 回答
  • 0 关注
  • 116 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信