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

java8 stream

标签:
Java

java8 stream的提出可以说改变了编程的一种思维。

sql化的表达

sql的表达是一种比较容易上手的语法结构,一直维护做什么的动作。
例如

select avg(num) from table1 where sum>5

对table里的num字段筛选,选出大于5的数字然后求平均值。
对于没有stream的java语言想表达这个。

    public static int cal(int[] data) {
        int totalNum = 0;
        int count = 0;
        for (int datum : data) {
            if (datum > 5) {
                count++;
                totalNum += datum;
            }
        }
        return totalNum / count;
    }

我们先得明白如何求平均,那是总数除以总个数,有筛选条件要以一个过滤,先去求出个数和总和。最后再来计算出平均值。
换成stream表达呢

    public static int calStream(int[] data) {
        double asDouble = Arrays.stream(data).filter((num) -> num > 5).average().getAsDouble();
        return new Double(asDouble).intValue();
    }

这里可能说是用了average这种内置的方法。所以显得很简洁了。如果抽象出一个方法来,也可以这样。我们来看看average的实现。

    public final OptionalDouble average() {
        long[] avg = collect(() -> new long[2],
                             (ll, i) -> {
                                 ll[0]++;
                                 ll[1] += i;
                             },
                             (ll, rr) -> {
                                 ll[0] += rr[0];
                                 ll[1] += rr[1];
                             });
        return avg[0] > 0
               ? OptionalDouble.of((double) avg[1] / avg[0])
               : OptionalDouble.empty();
    }

底层是一个collect的实现,第一个参数表示最终返回一个long的数组,里面有两个元素。第二个表示对于过来的元素的操作。和我们上面的代码表意是相同的。

              count++;
              totalNum += datum;

第三个操作,就是说我们要如何进行每个小的模块的组合。对于我们的用例来说,第三个步骤似乎是没有必要的。
现在如何说我们改动并行的程序来做这个事情呢,

    public static int calStream(int[] data) {
        double asDouble = Arrays.stream(data).parallel().filter((num) -> num > 5).average().getAsDouble();
        return new Double(asDouble).intValue();
    }

想并行化的话,直接加个parallel就可以了。
如果原来的java的写法。得先把数据平均分散多分,最好一个线程一段数据,然后每个数据进行过滤,然后求各自的sum和count。最后合并的时候,组合一下,每个的数据再一起加一下。
看看操作是不是和collect描述的一样的。
通过stream的编写方式不断的编写每个步骤要做什么,而且在大的框架下,保证了每个任务操作的并发性,最终保证了代码从串行到并行的转化。

stream的缺陷

上面提到sql的表达。我们也发现。下面是无法实现的。

select avg(num),max(num) from table1 where sum>5

目前的stream只是针对一份数据的操作。如果结果有多个,例如上面的有均值,有最大值,同时操作多个结果,目前是无法做到的。单纯的依靠sql并不能解决stream的所有的问题。

方便的转化操作

stream还带来了一个好处就是转化非常方便。例如我们用dbutil的工具,传入参数是一个Object[][]的二维数组。自己写还要先计算大小等等。如果用stream就很方便。

  int[][] ints = stringList.stream().map(s -> Integer.parseInt(s)).map(s -> new int[]{s}).toArray(int[][]::new);

这里把stream转化成对应的int,然后把每个元素作为一位数组,最终所有的一维数组组合成一个二维数组。
这里把非常复杂的代码转化成了一行。

小结

stream可以理解为单一结构的sql语法。这样可以快速的帮我们在stream的框架下进行求解操作。但是无法针对多结果的情况。
利用stream可以很快的把一个单线程程序,转化为多线程,加速的并发编程的效率。
数据的转化等操作,stream带来了极大的方便。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消