深入浅出Stream流
2021-7-30 9:45 作为一个刚进入社会毒打的小白Java开发工程师,真的是进了公司发现所学与所用旨不同,也可能是自己太菜了,常用jdk1.8连jdk1.8的新特性都不了解。
什么是stream流
Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediateoperation)的处理,最后由终端操作 (terminal operation) 得到前面处理的结果
举个例子:现在有一个学生类,里面有姓名和身高这个属性,我依次创建10个学生类,然后筛选出身高大于170身高学生的人,在没有接触stream流之前的或许你跟我大致一样的思路就是存放到一个集合中然后循环比较。stream流给我们提供了一个比较很好用的而且代码读起来更加通俗易懂
*filter()*方法
public static void main(String[] args) {
List<Student> studentList = initStudent();
List<Student> students =
studentList
.stream()
.filter(info -> info.getHeight() > 170)
.collect(Collectors.toList());
students.forEach(System.out::println);
}
public static List<Student> initStudent(){
List<Student> studentList = new ArrayList<>(10);
int height = 165;
for (int i = 0; i < 10; i++) {
studentList.add(new Student("张"+i,height));
height++;
}
return studentList;
}
我们可以看一下代码(写的比较简单hhh),首先第一点就是减少了代码量的编写,其次是在读代码这一观感上比较舒服,接下来我们对性能进行分析。首先了解一下stream的小小知识点
stream流的创建方式有两种
- 静态工厂
// TODO: 2021/8/1 loser 静态工厂方式创建stream流
Stream.of(1,2,3,4,5,6,9,8,7)
.filter(i -> i>5)
.collect(Collectors.toList())
.forEach(System.out::println);
- Arrays.stream()
// TODO: 2021/8/1 loser Arrays。stream()
list.stream()
.filter(i -> i>5)
.collect(Collectors.toList())
.forEach(System.out::println);
Stream流的分类
- 串行流:按照集合中的顺序对流进行处理
- 并行流:多个线程可以对集合中的数据同时进行处理(试用这种流要考虑到线程安全等问题)
终端操作与中间操作
学习stream流就要了解终端操作与中间操作
终端操作会消费 Stream 流,并且会产生一个结果,比如 iterator() 和 spliterator()。如果一个 Stream
流被消费过了,那它就不能被重用的。
中间操作会产生另一个流。需要注意的是中间操作不是立即发生的。而是当在中间操作创建的新流上执行完终端操作后,中间操作指定的操作才会发生。流的中间操作还分无状态操作和有状态操作两种。
- 在无状态操作中,在处理流中的元素时,会对当前的元素进行单独处理。比如,过滤操作,因为每个元素都是被单独进行处理的,所有它和流中的其它元素无关。
- 在有状态操作中,某个元素的处理可能依赖于其他元素。比如查找最小值,最大值,和排序,因为他们都依赖于其他的元素。
了解可以好好读一下stream的源码 无状态操作有好几个,累加也是无状态操作
stream有一个最基础的接口,叫做BaseStream,他包括了stream流中基本上最常用的方法
下面介绍几个实用的方法,stream作为jdk1.8的新特性支持链式、lambada的写法
我真是个懒狗 JDKApi文档的方法很多也很有一次这里我只介绍常用的方法
1.Stream distinct(),去重操作,将 Stream 流中的元素去重后,返回一个新的流。(中间操作)
public static void distInct(){
int count = 2;
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
list.add(count);
count++;
}
//使用Stream流进行去重操作
List<Integer> collect = list
.stream()
.distinct()
.collect(Collectors.toList());
//遍历进行比较
list.forEach(System.out::print);
System.out.println("");
collect.forEach(System.out::print);
}
2.reduce(T identity, BinaryOperator accumulator) 使用提供的身份值和 associative累积功能对此流的元素执行 reduction ,并返回减小的值。
public static void reduceOne(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Optional<Integer> reduce = list
.stream()
.reduce((a, b) -> a + b);
System.out.println(reduce.get()); //55
}
3.limit(long maxSize) 返回由此流的元素组成的流,截短长度不能超过 maxSize 。
/**
* limit 方法用来获取指定元素数量
* @param list
* @return
*/
public static List<Integer> limit(List<Integer> list){
return list.stream()
.limit(3)
.collect(Collectors.toList());
}
4.map(Function<? super T,? extends R> mapper) 返回由给定函数应用于此流的元素的结果组成的流。
/**
* map 用来处理一对多的元素
* @param list
* @return
*/
public static List<Integer> map(List<Integer> list){
// TODO: 2021/8/1 loser 对比两种写法还是觉得 toMap代码解读意更加明确
List<Integer> collect = list.stream().map(i -> i * i).distinct().collect(Collectors.toList());
list.stream().collect(Collectors.toMap(info -> info,info -> info*info)).forEach((k,v)->{
System.out.println(k+"==>"+v);
});
return collect;
}
5.sorted(Comparator<? super T> comparator) 返回由该流的元素组成的流,根据提供的 Comparator进行排序。
/**
* 对元素进行排序
* @param list
* @return
*/
public static List<Integer> sorted(List<Integer> list){
return list
.stream()
.sorted()
.collect(Collectors.toList());
}
6.mapToInt(ToIntFunction<? super T> mapper) 返回一个 IntStream ,其中包含将给定函数应用于此流的元素的结果。
public static void mapToInit(List<Integer> list){
// TODO: 2021/8/1 loser 相比较还有mapToDouble、mapToLong
IntSummaryStatistics statistics = list.stream().mapToInt(x -> x).summaryStatistics();
System.out.println("集合中最小的数"+statistics.getMin());
System.out.println("集合中最大的数"+statistics.getMax());
System.out.println("集合中求和的结果"+statistics.getSum());
System.out.println("集合中的平均数"+statistics.getAverage());
System.out.println("集合中的数字数量"+statistics.getCount());
}
简单介绍一下Collectors类
Collector实现各种有用的还原操作,如累加元件到集合,根据各种标准总结元件
简单来说,我看着官方文档我也看不懂
代码示例如下:
list.stream().collect(Collectors.toMap(info -> info,info -> info*info)).forEach((k,v)->{
System.out.println(k+"==>"+v);
});
就是将一个集合的对象转换为另一个集合比如list-map\
到此结束!!! 没啥好写的,本人用作复习浏览记忆,还请大佬们不要喷我,下章更新stream内存执行流程以及源码解析。