一、概念
Java8引入一个新特性是Stream流,允许以声明性方式处理数据集合,可以把Stream流看作是遍历数据集合的一个高级迭代器。
Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、过滤、集合等。
流的来源可以是集合、数组等,流不存储数据目的是处理数据,流只能使用一次。
Stream可以由数组或集合创建,对流的操作分为两种:
1.中间操作,每次返回一个新的流,可以有多个。
2.终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用,终端操作会产生一个新的集合或值。
二、Stream的创建
1.通过集合的stream()方法创建流
package day05;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class LambdaTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
}
}
2.使用Arrays.stream()方法用数组创建流
package day05;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class LambdaTest {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3};
Stream<Integer> stream = Arrays.stream(arr);
}
}
3.使用Stream.of()方法用数组创建流
package day05;
import java.util.stream.Stream;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class LambdaTest {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3};
Stream<Integer> stream = Stream.of(arr);
}
}
3.使用Stream静态方法创建流
package day05;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class LambdaTest {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3};
// Stream.of
List<Integer> integerList = Stream.of(arr).collect(Collectors.toList());
System.out.println(integerList);
// Stream.iterate
List<Integer> list = Stream.iterate(0, x -> x + 3).limit(2).collect(Collectors.toList());
System.out.println(list);
//Stream.generate
List<Double> doubleList = Stream.generate(Math::random).limit(3).collect(Collectors.toList());
System.out.println(doubleList);
}
}
stream和paralleStream的区别是:stream是顺序流,由主线程按顺序对流进行操作,而paralleStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数等。
三、常用操作
常用中间操作
方法 |
说明 |
filter |
用于筛选需要的数据 |
map |
用于映射出新数据 |
sorted |
用于数据排序 |
limit |
用于获取限制条数的数据 |
终端操作
方法 |
说明 |
forEach |
遍历数据 |
find/match |
匹配数据 |
reduce |
用于规约数据 |
max/min/count |
聚合数据 |
创建一个测试的实体类:
package day05;
/**
* @author qx
* @date 2023/11/3
* @des 测试类
*/
public class Student {
private String name;
private Integer age;
private Double salary;
public Student() {
}
public Student(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
1、遍历/匹配(foreach/find/match)
package day05;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> studentList = initStudents();
//forEach遍历
studentList.forEach(s -> System.out.println(s.getName()));
//findFirst获取第一个数据
Optional<Student> studentOptional = studentList.stream().findFirst();
System.out.println(studentOptional.get());
//findAny获取任意一个数据
Optional<Student> studentOptional1 = studentList.stream().findAny();
System.out.println(studentOptional1.get());
//match allMatch匹配所有
boolean flag = studentList.stream().allMatch(s -> s.getAge() > 20);
System.out.println(flag);
// noneMatch没有一个匹配
boolean nonedMatch = studentList.stream().noneMatch(s -> s.getAge() > 20);
System.out.println(nonedMatch);
// anyMatch匹配其中一个
boolean aniedMatch = studentList.stream().anyMatch(s -> s.getAge() > 20);
System.out.println(aniedMatch);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
张三
李四
王五
赵六
Student{name='张三', age=20, salary=3000.0}
Student{name='张三', age=20, salary=3000.0}
false
false
true
2.按条件匹配filter
package day05;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> studentList = initStudents();
// 筛选年龄超过22的数据
List<Student> students = studentList.stream().filter(s -> s.getAge() > 22).collect(Collectors.toList());
System.out.println(students);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
[Student{name='王五', age=25, salary=4000.0}, Student{name='赵六', age=23, salary=5000.0}]
3.聚合max、min、count
package day05;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> studentList = initStudents();
//max 获取年龄最大的对象数据
Optional<Student> maxOptional = studentList.stream().max(Comparator.comparing(Student::getAge));
System.out.println(maxOptional.get());
//min 获取年龄最小的对象数据
Optional<Student> minOptional = studentList.stream().min(Comparator.comparing(Student::getAge));
System.out.println(minOptional.get());
//count 获取列表的数量
long count = studentList.stream().count();
System.out.println(count);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
Student{name='王五', age=25, salary=4000.0}
Student{name='张三', age=20, salary=3000.0}
4
4.map和flatMap
package day05;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/6
* @des
*/
public class MapTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
// map 字符串的元素都改为大写
List<String> stringList = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(stringList);
//flatMap 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流
String[] arr = {"a,b,c,d", "e,f,g"};
List<String> strings = Arrays.asList(arr);
List<String> resultList = strings.stream().flatMap(s -> {
String[] array = s.split(",");
return Arrays.stream(array);
}).collect(Collectors.toList());
System.out.println(resultList);
}
}
输出:
[ZHANGSAN, LISI, WANGWU, ZHAOLIU]
[a, b, c, d, e, f, g]
5.规约reduce
归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
package day05;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> studentList = initStudents();
//对年龄求和
Optional<Integer> reduce = studentList.stream().map(s -> s.getAge()).reduce((x, y) -> x + y);
System.out.println(reduce.get());
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
90
6、收集(toList、toSet、toMap)
package day05;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> students = initStudents();
// toList
List<Student> studentList = students.stream().filter(s -> s.getAge() > 20).collect(Collectors.toList());
System.out.println(studentList);
// toSet
Set<Student> studentSet = students.stream().filter(s -> s.getAge() > 22).collect(Collectors.toSet());
System.out.println(studentSet);
// toMap
Map<String, Student> studentMap = students.stream().collect(Collectors.toMap(s -> s.getName(), Function.identity()));
System.out.println(studentMap);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
[Student{name='李四', age=22, salary=6000.0}, Student{name='王五', age=25, salary=4000.0}, Student{name='赵六', age=23, salary=5000.0}]
[Student{name='赵六', age=23, salary=5000.0}, Student{name='王五', age=25, salary=4000.0}]
{李四=Student{name='李四', age=22, salary=6000.0}, 张三=Student{name='张三', age=20, salary=3000.0}, 王五=Student{name='王五', age=25, salary=4000.0}, 赵六=Student{name='赵六', age=23, salary=5000.0}}
7.collect
Collectors提供了一系列用于数据统计的静态方法:
计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble
package day05;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> students = initStudents();
// 平均年龄
Double ageDouble = students.stream().collect(Collectors.averagingInt(s -> s.getAge()));
System.out.println(ageDouble);
// 求和
Integer ageSum = students.stream().collect(Collectors.summingInt(s -> s.getAge()));
System.out.println(ageSum);
// summarizingDouble统计所有数据
DoubleSummaryStatistics summaryStatistics = students.stream().collect(Collectors.summarizingDouble(s -> s.getSalary()));
System.out.println(summaryStatistics);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
22.5
90
DoubleSummaryStatistics{count=4, sum=18000.000000, min=3000.000000, average=4500.000000, max=6000.000000}
8.接合joining
joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
package day05;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> students = initStudents();
// 用逗号来拼接名字
String str = students.stream().map(s -> s.getName()).collect(Collectors.joining(","));
System.out.println(str);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
张三,李四,王五,赵六
9.排序sorted
package day05;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author qx
* @date 2023/11/3
* @des
*/
public class TestSupplier {
public static void main(String[] args) {
List<Student> students = initStudents();
// 按照年龄排序
List<Student> studentList = students.stream().sorted((s1, s2) -> s1.getAge().compareTo(s2.getAge())).collect(Collectors.toList());
System.out.println(studentList);
}
private static List<Student> initStudents() {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张三", 20, 3000.0));
studentList.add(new Student("李四", 22, 6000.0));
studentList.add(new Student("王五", 25, 4000.0));
studentList.add(new Student("赵六", 23, 5000.0));
return studentList;
}
}
输出:
[Student{name='张三', age=20, salary=3000.0}, Student{name='李四', age=22, salary=6000.0}, Student{name='赵六', age=23, salary=5000.0}, Student{name='王五', age=25, salary=4000.0}]