前天在某群里看见有人问Stream,我当时还以为是他写错了(一直用java7,偶尔用java8也从没有关注过新特性)
后来查了一下,原来这是java8的其中一个新特性
我也就是了解了下,还好能够理解,因此,写下本篇博文分享给大家
Stream他和Iterator有点类似但是区别也很大的
如下面的代码,我们遍历一个list
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Iterator<Integer> iter = list.iterator(); while(iter.hasNext()){ int a = iter.next(); if(a % 2 ==0){ System.out.println(a*2+1); } }以上代码,我们判断如果这个数被2整除,就将这个数乘2再加1,并且打印出来
下面我们看看使用Stream如何实现
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Stream<Integer> stream = list.stream(); stream.filter((x) -> { return x % 2 == 0; }).map((x) -> { return x * 2+1; }).forEach(System.out::println);
像不像建造者模式这里 呵呵
Stream处理这个问题,他分成了三部分
第一部分,筛选
筛选符合要求的数据
第二部分,业务逻辑处理
这里开始处理的你的数据,业务逻辑处理
第三部分,展示
给客户看的东西
这三部分是延迟的,我们使用hibernate的时候常常听说延迟加载,这里的意思基本一样,也就是说您可以把map去掉,也可以把forEach去掉
当我们需要用到业务逻辑处理的时候,我们就加上map,当我们需要为客户展示的时候,我们就可以forEach,当然,forEache也可以是toArray
如下面的代码片段
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Stream<Integer> stream = list.stream(); stream.filter((x) -> { return x % 2 == 0; }).map((x) -> { return x * 2+1; }).toArray();toArray 将最后的数据转换为了 Object[] array,你可以试试,打印出这个数组。
上面的写法可能您第一次看不懂,尤其是 -> 这是什么意思,以及 :: 这个是意思?我也看不懂,不过后来我根据源码,向下面这样写以上代码也可以可以正常运行的,因此也就不难理解符号 -> 和 :: 了
请看如下代码
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Stream<Integer> stream = list.stream(); stream.filter(new Predicate<Integer>(){ @Override public boolean test(Integer t) { return t % 2 == 0; } }).map(new Function<Integer, Integer>(){ @Override public Integer apply(Integer x) { return x * 2+1; } } ).forEach(new Consumer<Integer>(){ @Override public void accept(Integer t) { System.out.println(t); } } );首先我们看看filter这个方法,这个方法返回一个Stream(建造者模式嘛)
源码是这样表示的
Stream<T> filter(Predicate<? super T> predicate);
Stream<T> filter(Predicate<? super T> predicate);
也就是说filterde的参数是predicate接口
而predicate接口的泛型类型是T的超类
T是什么?
T是您定义的数据类型的类型,此处是Integer
那么我们就写了一个内部类来实现这个参数的传递
而这个接口我们只需要实现一个test方法,也只有这个方法可以让您实现
注意泛型T是predicate接口的泛型类型
这个我们刚刚说了传递给predicate接口的泛型是Integer的超类(T太多了,不要搞混了,每个类的T不一样,这不用我说吧)
我们这里传递给predicate接口的类型是Integer
所以test方法的类型就是是Integer
predicate接口的test类我们可以看到他的方法是这样定义的
boolean test(T t);也就是test的参数是Integer类型
然后根据这个参数来筛选,符合要求的值,返回一个boolean类型,
因此我们上面的filter就是这样写的
stream.filter(new Predicate<Integer>(){ @Override public boolean test(Integer t) { return t % 2 == 0; } })然后根据上面的方法,就不难理解我上面代码中的map和forEach的写法了
需要注意的是map方法中的
new Function<Integer, Integer>
new Function<Integer, Integer>第一个Integer是我们传递过来的类型
第二个Integer是我们返回给forEach等其他处理函数处理的类型
就是说forEach里面的Consumer的泛型必然是和Function的第二个类型一致
那么最上面的代码中关于符号 -> 和 :: 的理解
stream.filter((x) -> { return x % 2 == 0; }).map((x) -> { return x * 2+1; }).forEach(System.out::println);
-> 我可以理解为,默认实现一个接口,x表示传入的参数和类型,此时的x的类型肯定是Integer了,因为我们定义的就是Integer类型
:: 我可以理解为默认实现一个接口,这个接口方法无返回值
目前我认为这两个符号可能只针对可以重写接口的一个方法,如果又两个或以上的方法,我暂时没有测试,如果您测试了,烦请告知我噢
爆款云服务器s6 2核4G 低至0.46/天,具体规则查看活动详情