上面一章 我们讲了lambda表达式 juejin.im/post/5b5fd7…
- 今天我们讲的stream流,也会在lambda基础上面
一、stream初识
我们在处理业务逻辑处理的时候,做的最多的就是集合的操作,不管什么的list啊、map啊各种遍历,组合,筛选在我们脑海中翻滚。 举个例子:
String contents = "ddada.faqwewq.dsadasdasddsas.sda.dadqweqd.sadas.gfhfhjhgngh";
List<String> words = 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
*/
@Data
public class Student {
/**
* 学号
*/
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
}
/**
* 班级
*
* @author tianyi
*/
@Data
public class ClassGrade {
/**
* 年级
*/
private int gradeLeven;
/**
* 班
*/
private int grade;
/**
* 班级里的学生
*/
private List<Student> students;
}
复制代码
- filter
上面实例已经看到了filter()相当于if()一个条件判断
List<Student> students = new ArrayList<>();
List<Student> 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
对流进行元素进行操作,组合成新的流
List<String> names = students.stream()
.filter(student -> student.getAge() > 18)
.map(Student::getName).collect(Collectors.toList());
复制代码
- 这边将过滤的流中的姓名元素拿出来,组合成新的流,在组合成List集合
- flatMap
将拿到的元素进行扁平化操作,其实我也说不清这个名词,看一下代码也就都知道了
//班级集合
List<ClassGrade> classGrades = new ArrayList<>();
//将所有班级的学生组成新集合
List<Student> 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 Stream<T> extends BaseStream<T, Stream<T>>
复制代码
- 其中还要讲个一个类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.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
* @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
*/
Optional<T> findFirst();
/**
* Returns an {@link Optional} describing some element of the stream, or an
* empty {@code Optional} if the stream is empty.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
* <p>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()
*/
Optional<T> findAny();
复制代码
- 我们自己写一段代码试试看,这个到底是什么怎么用
//Optional 类
//拿到所有班级学生的第一个
Optional<Student> studentOptional;
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我们下一章讲,绝对好用,代码码起来自己都害怕