流 stream
流的概念:流是在java8里面引入的一个新的api,在Java.util包下,他允许用声明的性的方式来处理数据集合,也就是允许你直接用语句来表达你要实现的东西,而不是写一个方法的实现,其实流就是一个处理集合数据的高级迭代器,同时它是并行处理数据,比普通的数据处理会更快.
public static void main(String[] args) {
Apple apple = new Apple("苹果1",2,"green");
Apple apple1 = new Apple("苹果5",3,"red");
Apple apple2 = new Apple("苹果4",4,"green");
Apple apple3 = new Apple("苹果3",4,"red");
Apple apple4 = new Apple("苹果2",4,"green");
List<Apple> list = new ArrayList<>();
list.add(apple);
list.add(apple1);
list.add(apple2);
list.add(apple3);
list.add(apple4);
//Java7 处理3个苹果
//1.赛选所有绿色的苹果i哦
List<Apple> listApples = new ArrayList<>();
for (Apple apple5 : list) {
if ("green".equals(apple5.getColor())){
listApples.add(apple5);
}
}
//2.进行排序
Collections.sort(listApples, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Integer.compare(o1.getNum(),o2.getNum());
}
});
//3 将所有赛选出来的拼过的名字从新收集起来
List<String> listApplesName = new ArrayList<>();
for (Apple listApple : listApples) {
listApplesName.add(listApple.getName());
}
//java8 利用流处理集合
List<String> collect = list.stream()
.filter(apple5 -> "green".equals(apple5.getColor()))//过滤绿色苹果
.sorted(Comparator.comparing(Apple::getNum).reversed())//倒序排序苹果数量
.map(Apple::getName)//收集名字
.collect(Collectors.toList());//重新放入集合
}
从这个简单的小案例可以看stream的强大之处,处理数据更加简单方便.条件处理更加清晰,完全可以让我们节约更多的时间去跟妹儿聊聊天.
上面代码中的filter,sorted,map操作都会返回一个新的流,他们就结成了一条流水线,我们可以把它当成一个对源数据的查询操作,然后利用collect进行一个收集处理
filter:传入一个lambda表达式进行过滤操作
sorted:传入一个Java util包下的排序处理器进行排序操作
map:传入一个lambda表达式,将自己需要的信息进行一个提取
collect:将处理过的流程按照自己所需要的数据集进行一个转换,这里的toList则是我们需要的结果方案
这里,我们只对上面代码进行一个简短的解释,后面会有更多用法的讲解
流的特点
1.只能遍历一次
流跟迭代器类似,每一次遍历完之后都会被消费掉,但是会从原始数据源哪里获取一个新的流来重新遍历一次,如果对同一个流进行多次遍历会被抛出异常
Stream<Apple> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);
异常信息
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.base/java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at com.example.demo.TestStream2.main(TestStream2.java:58)
2.外部迭代和内部迭代
外部迭代:外部迭代就是一个显式迭代就是我们能直接看的迭代,for循环就一个我们明显看到的外部迭代
内部迭代:stream使用的就是内部迭代,stream直接帮你把迭代做了,把处理过的流给存在某个地方,前提是你只要给他一个函数告诉他他该做什么就行了
内部迭代的好处:在迭代的同时项目可以并行处理数据,Streams库的内部迭代可以自动选择一种合适你硬件的数据表示和并行实现,相比外部迭代,我们就不用去关心并行所造成数据困扰了,也就是不用操心在synchronizd的怎么使用,用哪里的问题了
3.流操作
中间操作:
操作 | 操作参数 |
---|---|
filter | predicate<T> |
map | Function<T,R> |
limt | number |
sorted | Comparator<T> |
distinct |
终端操作:
操作 | 操作目的 |
---|---|
forEach | 对流中数据进行操作,返回void |
count | 对流中元素经行统计,返回long |
collect | 对流元素进行规约成想要的数据,可以是list,map等 |
总结
其实流的基础的东西并不多,最主要的是在看自己在各种场景的对流进行一个跟好的使用,在下次的更新中我会跟大家一个分享各种流的使用
资料来源 java8 实战