-
Java 8 添加了一个新的抽象称为流 Stream API,可以让你以一种声明的方式处理数据。
-
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
-
Stream API 可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
-
视频教程:https://doc.iocoder.cn/video/
-
stream()
− 为集合创建串行流。在串行流中,每个元素都是由同一个线程处理的,因此操作是顺序执行的。
-
parallelStream()
− 为集合创建并行流。在并行流中,流会将集合分成多个子集,然后多线程并行处理这些子集中的元素。
/**
* 集合创建流
*/
List list = new ArrayList<>();
//串行流
Stream stream = list.stream();
//并行流
Stream stream = list.parallelStream();
通过数组创建的方式有:
Stream.of()
、
Stream.generate()
、
Stream.iterate()
、
IntStream
、
LongStream
等,如下代码。
/**
* 数组创建流
*/
String[] strs = new String[3];
Stream stream1 = Arrays.stream(strs);
/**
* Stream.of() 创建流
*/
Stream stream2 = Stream.of("Apple", "Orange", "Banana");
/**
* Stream.generate()创建流
*/
Stream randomStream = Stream.generate(Math::random).limit(5);
/**
* Stream.iterate()创建流
*/
Stream integerStream = Stream.iterate(0, n -> n + 2).limit(5);
/**
* IntStream创建流
*/
IntStream intStream = IntStream.range(1, 5); // [1,2,3,4]
/**
* LongStream创建流
*/
LongStream longStream = LongStream.rangeClosed(1, 5); // [1,2,3,4,5]
通常,我们遍历一个集合时会使用
for(int i = 0; i < list.size(); i++)
这种方式,但是当我们有 IntStream 可用时,可以优化为使用
IntStream.rangeClosed(0, list.size() - 1).forEach(i -> {...})
来遍历集合。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/yudao-cloud
-
视频教程:https://doc.iocoder.cn/video/
过滤操作,可以保留满足过滤条件的元素。如下代码为:将 lists 流中的等于 1 的元素过滤出来,并打印结果。
/**
* filter 过滤操作
* @param lists
*/
public static void filterTest(List lists){
List integers = lists.stream()
.filter(list ->Objects.equals(1, list)).toList();
integers.forEach(System.out::println);
}
映射操作,可以对流中的每个元素提取并转换。如下代码为:
-
map 映射操作:
将 lists 流中的字符串,处理成大写的字符串;
-
flatMap 映射操作:
将 lists 流中的二位数组,转成一维数组。(flatMap 用于将流中的一个元素转换为一个流,然后将所有转换后的流组装成一个流)
/**
* map映射操作
*/
public static void mapTest(List lists){
lists.stream().map(String::toLowerCase).toList();
lists.forEach(System.out::println);
}
/**
* flatMap映射操作,将嵌套集合转换为扁平集合
*/
public static void flatMapTest(List> lists)
{
lists = Arrays.asList(
Arrays.asList("Java", "Kotlin"),
Arrays.asList("Python", "Ruby"),
Arrays.asList("JavaScript", "TypeScript")
);
List wordList = lists.stream().flatMap(List::stream).toList();
wordList.forEach(System.out::println);
}
mapToInt
/
mapToLong
/
mapToDouble
操作,可以将流中的元素映射为对应
int
/
Long
/
Double
类型,并进一步做数值计算。
public class Student{
//年龄
private int age;
//姓名
private String Name;
}
public static void mapTest(){
int totalAge1 = students.stream().mapToInt(Student::getAge).sum();
Long totalAge2 = students.stream().mapToLong(Student::getAge).sum();
Double totalAge3 = students.stream().mapToDouble(Student::getAge).sum();
}
排序流中的元素。
/**
* 排序操作 sorted,对于集合对象排序,必须实现 Comparable接口,并重写 compareTo 方法,如果没有实现则需要给 sorted 函数传递参数
*/
public static void sortedTest(){
List cities = Arrays.asList("New York", "Tokyo", "London", "Paris");
// 对城市按字母顺序排序
List sortedStream = cities.stream().sorted(Comparator.comparingInt(city -> city.charAt(1))).toList();
sortedStream.forEach(System.out::println);
}
去除流中的重复元素。
/**
* 去重操作(distinct)
*/
public static void distinctTest(){
List cities = Arrays.asList("New York", "Tokyo", "London", "Paris");
// 对城市去重
List distinctStream = cities.stream().distinct();
sortedStream.forEach(System.out::println);
}
/**
* 截断操作(limit),只取流中前3个元素
*/
List numbers = Lists.newArrayList(1, 2, 3, 4, 5, 6);
List limitedList = numbers.stream().limit(3).collect(Collectors.toList());
/**
* 跳过操作(skip),跳过流中前3个元素
*/
List numbers = Lists.newArrayList(1, 2, 3, 4, 5, 6);
List limitedList = numbers.stream().skip(3).collect(Collectors.toList());
/**
* 观察操作,用于调试和观察流中的元素
*/
List words = Arrays.asList("apple", "banana", "orange");
List modifiedWords = words.stream()
.filter(word -> word.length() > 5)
.peek(word -> System.out.println("Filtered Word: " + word))
.map(String::toUpperCase)
.peek(word -> System.out.println("Uppercase Word: " + word))
.collect(Collectors.toList());
迭代操作,可以用于遍历流中的每一个元素。
List fruits = Arrays.asList("apple", "banana", "orange");
fruits.stream().forEach(fruit -> System.out.println(fruit));
//fruits.forEach(fruit -> System.out.println(fruit));
//fruits.stream().forEach(System.out::println);
收集操作,可以将流转换为 List、Set、Map 等集合。通过 collect 函数,对流中的元素进行收集。
// 将学生流转换为 List
List limitStu = students.stream().collect(Collectors.toList());
// 将学生流转换为 Set
List limitStu = students.stream().collect(Collectors.toSet());
// 将学生流转换为 Map,将年龄作为 key,将学生信息作为 value (Function.identity() 为提取元素自身的函数,(e1, e2)-> e1 代表当两个学生年龄相同时,取第一个学生)
Map studentMap = students.stream().collect(Collectors.toMap(
Student::getAge,
Function.identity(),
(e1,e2) -> e1));
//将学生的名字通过逗号拼接成一个字符串:studentName
String studentName = students.stream().map(Student::getName).collect(Collectors.joining(","));
//通过字符串的长度对 fruits 流分组
List fruits = Arrays.asList("apple", "banana", "orange");
Map> lengthToNamesMap = fruits.stream()
.collect(Collectors.groupingBy(String::length));