赞
踩
推出了一些很好用的新特性 这里先讲一下stream 流
这个名字本身就容易让新手混淆,因为编程领域里面有很多东西名字都带有stream,比如BIO 里面有的IO流 inputstream ,outputstream, 比如大数据里面有流式计算,会有什么什么steam之类的。
但是这篇说的跟上面这些没有毛线关系,这里的stream指的是 java 8里面新引入的一套API :流 stream
怎么理解这个东西? 应该说他是一种对java集合(比如数组 比如list 比如map)的操作抽象,在没有stream之前,我们常见的集合操作,比如list, 我们可以遍历这个list , 可以查找这个list中某个元素,可以对list中的元素做处理,比如按条件过滤后 生成新的list等等等。 而stream流的引进就是帮我们抽象了这些常用的操作,所以它是本质上一个处理数据的过程。
这里举一个很形象的例子 就是sql里面的视图, 视图不是具体的数据 它是把你对sql的一些复杂操作 抽象起来,它是一个数据计算的过程。 所以我们在理解jdk8的stream流的时候 很重要的一点就是 它不是一个数据结构 不是一个集合,它是一种处理数据计算数据的过程抽象,它本身不存储数据 也不会改变源对象集合。
Stream APl对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之,StreamAPI提供了一种高效且易于使用的处理数据的方式。
再举一个例子 比如你有一个面包, 然后你想切它,那么你自己指定了一个过程规则:横竖两刀 切 切成4块, 然后每当你拿到一个面包 你就直接用这个规则去切它,这个面包就是数据集合 而你指定的这个切面包的规则和切的过程就是stream流。 它只是一个处理过程 而不是面包本身。
java 8 提供了 并行流(并发场景中使用) 和 串行流 (常用的同步场景),大多数情况下 我们使用的都是 串行流,用来在代码中对 各种集合进行高效 易用的操作。
这里就是核心了 上面讲了 stream引入java8 它的最大作用就是对集合进行操作。 那么它能进行哪些操作呢?
我们先来一个大概的分类:
主要关注最常用的前两种,新手先不用管第三者。
在下面的表格在有各种 ***() 方法 全部是steam可以对集合进行各种操作,第一眼看名字就知道常用的 什么查找 排序 筛选 映射等 啥都有,之前这些操作都需要你手写,现在好了 可以直接白嫖!
这些操作被分为两大类 中间操作和终止操作。
这个很好理解 中间操作就是 stream对集合进行操作 操作的结果暂时还是stream意思就是说它还在对集合的操作过程当中, 而终止操作就是stream对集合操作结束 得到结果是一个新的集合 说明stream执行结束了。
理论都懂了 现在就这里面的一些经常用的操作 来实践一下 体会一下stream操作的感觉。
既然是对集合操作 那我们先随便搞一个测试用的集合
list<Student
创建一个student类的集合属性依次是 id 姓名 排名 性别 true/false =男/女
List<Student>studentList = new LinkedList<>();
studentList.add(new Student(1L,"maru",1,true));
studentList.add(new Student(2L,"serral",13,true));
studentList.add(new Student(3L,"dark",25,false));
studentList.add(new Student(4L,"zest",40,true));
studentList.add(new Student(5L,"time",42,false));
studentList.add(new Student(6L,"clem",50,true));
studentList.add(new Student(7L,"solar",65,true));
stream 操作函数很多 这里主要说一下 最常用的几个操作 ,理解之后其他的一通百通 用的时候直接搜即可,我们平时在业务代码里面最常用到的有:
filter 是过滤用的 可以把过滤条件作为参数 :
比如我们按排名<30 过滤上面的student:
studentList.stream().filter(student -> student.getRanking() < 30)
这里的filter(student -> student.getRanking() < 30) 你可以理解为数据里面的函数,函数入参是student对象,——> 后对每一个对象做条件过滤操作。 就可以筛选出 student.getRanking() < 30 的对象。
但是前面说了filter是中间操作 所以上面代码得到的是一个流 而不是list对象。 所以后面加上收集器:
List<Student> studentsOfFilter = studentList.stream().filter(student -> student.getRanking() < 30).collect(Collectors.toList());
就这样 执行一下 一个过滤流操作就完成了:
按ranking过滤_输出结果:
maru
serral
dark
Process finished with exit code 0
这里就体现了stream的便捷性,如果按照传统的方法 我们还得新建一个list for循环判断过滤旧list 然后符合条件的放到新的list里面。
注意 filter的操作对象结构是 List 操作完之后得到的结构还是List,后面的map就不是这样了。
map应该是平时用的最多的,map的理解是 映射到新集合。 注意第一是映射 ,第二是新集合,map的用途很多都是我们业务场景中 你有一个list<A 需要把A类里面的一些属性取出来处理一下 set到 B类 然后 形成一个list<B . map支持
非常灵活。
比如上面的 list<student 我们现在只想要 里面的name那一列 单独成一个list<String:
List<String> nameList = studentList.stream().map(s -> s.getName()).collect(Collectors.toList());
一行代码就搞定了。
再比如 我们现在是 student 我们再创建一个 scplay类 把list<student 映射过去:
public class ScPlayer {
//姓名
private String name;
//年级排名
private int grade;
//性别
private String race;
}
List<ScPlayer> scPlayers = studentList.stream().map(s -> {
ScPlayer scPlayer = new ScPlayer();
scPlayer.setName(s.getName());
if (s.getRanking() < 10) {
scPlayer.setGrade(1);
} else if (s.getRanking() >= 11 && s.getRanking() < 20) {
scPlayer.setGrade(2);
} else {
scPlayer.setGrade(3);
}
scPlayer.setRace("Terran");
return scPlayer;
}).collect(Collectors.toList());
scPlayers.forEach(System.out::println);
这里方法里面变成了{ } ,因为里面创建新对象 记得最后要return返回
再说两个判断用的,会用过滤条件对 集合内的所有元素进行判断,any就是只要有一个符合就true,all就是全部符合才行:
//anymatch
boolean anyMatch40 = studentList.stream().anyMatch(s -> s.getRanking() == 40);
System.out.println("anyMatch40: "+anyMatch40);
//allmatch
boolean allMatch40 = studentList.stream().allMatch(s -> s.getRanking() == 40);
System.out.println("allMatch40: "+allMatch40);
anyMatch40: true
allMatch40: false
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。