java8新特性 Stream的一般用法 API详细分析 代码测试以及符号 -> 和 :: 的个人理解

前天在某群里看见有人问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);


像不像建造者模式这里 呵呵

java 23种设计模式之创建型—建造者模式(4)


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/天,具体规则查看活动详情Blog Img