我们讲了lambda表达式
- 今天我们讲的stream流,也会在lambda基础上面
一、stream初识
我们在处理业务逻辑处理的时候,做的最多的就是集合的操作,不管什么的list啊、map啊各种遍历,组合,筛选在我们脑海中翻滚。 举个例子:
String contents = "ddada.faqwewq.dsadasdasddsas.sda.dadqweqd.sadas.gfhfhjhgngh";Listwords = Arrays.asList(contents.split("."));int count = 0;for (String word : words) { if (word.length() > 5) { count++; }}System.out.println("字段超过5的个数:" + count);复制代码
我们采用stream的写法
long count = words.stream().filter(word -> word.length() > 5).count();System.out.println("字段超过5的个数:" + count);复制代码
- 这边的stream的流其实和io里面的流没有关系,一开始不要往那边理解,看看包名就知道的。
- 首先通过.stream()创建了一个流
- 对于流就行过滤.filter
- .count()返回过滤结果的个数
- stream不会对words这边集合进行操作,都是对流进行操作,所以原来的word是不会变的
二、转换流
我在敲代码的时候经常用的是三个方法进行转换流filter、map、flatMap,我创建两个实体类同来举例子
/** * 学生实体类 * * @author tianyi */@Datapublic class Student { /** * 学号 */ private Integer id; /** * 姓名 */ private String name; /** * 年龄 */ private int age;}/** * 班级 * * @author tianyi */@Datapublic class ClassGrade { /** * 年级 */ private int gradeLeven; /** * 班 */ private int grade; /** * 班级里的学生 */ private Liststudents;}复制代码
- filter
上面实例已经看到了filter()相当于if()一个条件判断
Liststudents = new ArrayList<>();List newStudents = new ArrayList<>();for (Student student : students) { if (student.getAge() > 18) { newStudents.add(student); }}newStudents = students.stream() .filter(student -> student.getAge() > 18) .collect(Collectors.toList());复制代码
- 对于students集合转换为流,进行过滤年龄大于18岁的,重新组成新集合。所有操作只针对stream对元集合studets没有影响,需要返回新集合。.collect(Collectors.toList())这个也是java8提供的新方法,后面也会讲,这边就是讲流组成新集合。
- map
对流进行元素进行操作,组合成新的流
Listnames = students.stream() .filter(student -> student.getAge() > 18) .map(Student::getName).collect(Collectors.toList());复制代码
- 这边将过滤的流中的姓名元素拿出来,组合成新的流,在组合成List集合
- flatMap
将拿到的元素进行扁平化操作,其实我也说不清这个名词,看一下代码也就都知道了
//班级集合ListclassGrades = new ArrayList<>();//将所有班级的学生组成新集合List studentList = new ArrayList<>();for(ClassGrade classGrade: classGrades){ studentList.addAll(classGrade.getStudents());}studentList = classGrades.stream() .flatMap(classGrade -> classGrade.getStudents().stream()) .collect(Collectors.toList());复制代码
- 将所有班级学生拿出来组成新集合
三、结果收集
刚才我们看到了.count()/.collect(Collectors.toList())这边都是将流转换,其实还有很多api接口,详细可以看下java.util.stream包下面的
public interface Streamextends BaseStream >复制代码
- 其中还要讲个一个类Optional Stream接口里面有好几个方法返回类型是Optional
/** * Returns an { @link Optional} describing the first element of this stream, * or an empty { @code Optional} if the stream is empty. If the stream has * no encounter order, then any element may be returned. * *This is a short-circuiting * terminal operation. * * @return an {
@code Optional} describing the first element of this stream, * or an empty { @code Optional} if the stream is empty * @throws NullPointerException if the element selected is null */OptionalfindFirst();/** * Returns an { @link Optional} describing some element of the stream, or an * empty { @code Optional} if the stream is empty. * * This is a short-circuiting * terminal operation. * *
The behavior of this operation is explicitly nondeterministic; it is * free to select any element in the stream. This is to allow for maximal * performance in parallel operations; the cost is that multiple invocations * on the same source may not return the same result. (If a stable result * is desired, use {
@link #findFirst()} instead.) * * @return an { @code Optional} describing some element of this stream, or an * empty { @code Optional} if the stream is empty * @throws NullPointerException if the element selected is null * @see #findFirst() */OptionalfindAny();复制代码
- 我们自己写一段代码试试看,这个到底是什么怎么用
//Optional 类//拿到所有班级学生的第一个OptionalstudentOptional;Student student;//拿到Optional,判断是否为null进行取值studentOptional = classGrades.stream() .flatMap(classGrade -> classGrade.getStudents().stream()).sorted().findFirst();if(studentOptional.isPresent()){ student = studentOptional.get();}//为空的话,自己new 值student = classGrades.stream() .flatMap(classGrade -> classGrade.getStudents().stream()).sorted().findFirst().orElse(new Student());//还可以抛异常student = classGrades.stream() .flatMap(classGrade -> classGrade.getStudents().stream()).sorted().findFirst().orElseThrow(NullPointerException::new);复制代码
Optional类这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。是不是我们的空指针异常没得了呢-,-
- 还有关于stream结果收集的api我们下一章讲,绝对好用,代码码起来自己都害怕