欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java se 8 学习(二、stream API)

程序员文章站 2022-06-09 21:12:33
...

上面一章 我们讲了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里面的流没有关系,一开始不要往那边理解,看看包名就知道的。
  1. 首先通过.stream()创建了一个流
  2. 对于流就行过滤.filter
  3. .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;
}
复制代码
  1. 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提供的新方法,后面也会讲,这边就是讲流组成新集合。
  1. map

对流进行元素进行操作,组合成新的流

List<String> names = students.stream()
        .filter(student -> student.getAge() > 18)
        .map(Student::getName).collect(Collectors.toList());
复制代码
  • 这边将过滤的流中的姓名元素拿出来,组合成新的流,在组合成List集合
  1. 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>>
复制代码
  1. 其中还要讲个一个类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我们下一章讲,绝对好用,代码码起来自己都害怕

源码 github.com/Radicalpro/…

转载于:https://juejin.im/post/5b6126fb6fb9a04f87521eaf