当前位置 博文首页 > Java知音号:SQL中那么多函数,Java8为什么还要提供重复的Stream

    Java知音号:SQL中那么多函数,Java8为什么还要提供重复的Stream

    作者:Java知音号 时间:2021-05-23 18:21

    有个同学提出一个这样的疑问;

    在业务系统中,数据一般都从sql中查询,类似使用where,order by,limit,聚合函数等,为什么还要用java8的Stream方法?

     

    对这个问题,大家有什么见解,欢迎评论区留言

    SQL中那么多函数,Java8为什么还要提供重复的Stream方法,多此一举?

    首先,我们可以看下Stream的方法。

    stream三种创建方式

    • 集合 Collection.stream()
    • 静态方法 Stream.of
    • 数组 Arrays.stream

    Stream的终止操作

    • foreach(Consumer c) 遍历操作
    • collect(Collector) 将流转化为其他形式
    • max(Comparator) 返回流中最大值
    • min(Comparator) 返回流中最小值
    • count 返回流中元素综述

    Collectors 具体方法

    • toList List<T> 把流中元素收集到List
    • toSet Set<T> 把流中元素收集到Set
    • toCollection Coolection<T> 把流中元素收集到Collection中
    • groupingBy Map<K,List<T>> 根据K属性对流进行分组
    • partitioningBy Map<boolean, List<T>> 根据boolean值进行分组

    Stream的中间操作

    • filter(Predicate) 筛选流中某些元素
    • map(Function f) 接收流中元素,并且将其映射成为新元素,例如从student对象中取name属性flatMap(Function f) 将所有流中的元素并到一起连接成一个流
    • peek(Consumer c) 获取流中元素,操作流中元素,与foreach不同的是不会截断流,可继续操作流
    • distinct() 通过流所生成元素的equals和hashCode去重
    • limit(long val) 截断流,取流中前val个元素
    • sorted(Comparator) 产生一个新流,按照比较器规则排序
    • sorted() 产生一个新流,按照自然顺序排序

    匹配

    • booelan allMatch(Predicate) 都符合
    • boolean anyMatch(Predicate) 任一元素符合
    • boolean noneMatch(Predicate) 都不符合

    以上列举了一些Stream()常用操作方法,其实大部分在SQL中都能实现,同时类似Oracle,MySQL等数据库,有无数大牛用了十几年的时间帮我们做这些操作的优化处理,自带优化到极致的索引和缓存。所以如果在数据量大的情况下,有条件使用SQL处理,理论上比Stream提供的方法要快。

    Stream大部分功能重叠了SQL自带函数方法,既然这样,Java8为什么还要提供这类API呢,效率你又干不过人家?

    Stream有自己的使用场景,现在微服务越来越流行,一个系统被拆N多个服务,每个服务又使用不同的数据库,但是往往不同服务之间,在数据上有交叉。这种情况下,在SQL上的处理就会变得很麻烦。

    比如,现在有A服务(会员管理),存储了会员信息,包括会员等级、登记日期、近期消费情况等。B服务(注册用户管理),存储了用户基本信息,包括住址、联系电话、生日等;想要总览会员信息,VVIP会员需要在生日时候送上一条彩信祝福和一款不值钱的库存商品作为礼物。

    统计或者总览会员信息的时候,你就没办法用一条SQL去搞定了,这时候,Stream的分组,过滤,匹配等函数就发挥了作用。Java8之前,这些操作可能需要用循环或者iterator来做,比较繁琐,而Stream流可以很顺畅的一口气实现之前需要大段代码才能实现的功能。

    如:

    筛选大于18岁的会员

    List<VIPUsers> collect = lists.stream().filter(e -> e.getAge() > 18).collect(Collectors.toList());

    根据会员类型分组

    Map<String, List<VIPUsers>> collect3 = lists.stream()
            .collect(Collectors.groupingBy(vUser::getType));

    统计总数

    long count = lists.stream().count();

    都可以很方便的操作。

    Stream是Java8对集合操作的优化,相较于迭代器,使用Stream的速度非常快,并且它支持并行方式处理集合中的数据,默认情况能充分利用cpu的资源。同时支持函数式编程,代码非常简洁。在日常开发中使用Stream,开发效率更快,代码更加简洁。

    但是需要注意的是,不要过分依赖Stream操作,常用的过滤聚合分组等操作,如果Stream和SQL都能处理的场景下,更建议去使用SQL去操作,尤其是数据量大的情况下,要充分利用数据库自带的缓存和索引,不要想着自己去优化。

    老潘说过,叔怕你把握不住啊孩子,让数据库来!!!

    bk