Java Stream(流)是Java 8引入的一个强大的新特性,用于处理集合数据。它提供了一种更简洁、更灵活的方式来操作数据,可以大大提高代码的可读性和可维护性。本文将详细介绍Java Stream流的概念、用法和一些常见操作。
目录
初始化数据
// 模拟数据1
public List<Student> getList(){
List<Student> studentList = new ArrayList<>(5);
Student student1 = new Student("张三", "001", 60, 80d, 0);
Student student2 = new Student("李四", "001", 62, 82d, 0);
Student student3 = new Student("王五", "002", 64, 84d, 0);
Student student4 = new Student("赵六", "002", 66, 86d, 1);
Student student5 = new Student("齐七", "003", 68, 88d, 2);
studentList.add(student1);
studentList.add(student2);
studentList.add(student3);
studentList.add(student4);
studentList.add(student5);
return studentList;
}
// 模拟数据2
public List<String> getListStr(){
List<String> list = new ArrayList<>();
list.add("A");
list.add("C");
list.add("B");
list.add("C");
return list;
}
实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private String classes;
private Integer score1;
private Double score2;
private Integer type;
public Student(Integer score1, Double score2) {
this.score1 = score1;
this.score2 = score2;
}
}
一、基本玩法
1.1 List转Map
item中的某个字段作为key, value为对象本身
/**
* list转map name作为key, value为student
*/
@Test
public void test01(){
List<Student> studentList = getList();
// list转map name作为key, value为student
Map<String, Student> studentMap = studentList.stream()
.collect(Collectors.toMap(Student::getName, student -> student));
studentMap.forEach((k, v) ->{
System.out.println("k=" + k + ", v=" + v.toString());
});
}
打印结果:(点击左侧小三角显示)====================================>
k=齐七, v=Student(name=齐七, classes=003, score1=68, score2=88.0, type=2)
k=李四, v=Student(name=李四, classes=001, score1=62, score2=82.0, type=0)
k=张三, v=Student(name=张三, classes=001, score1=60, score2=80.0, type=0)
k=王五, v=Student(name=王五, classes=002, score1=64, score2=84.0, type=0)
k=赵六, v=Student(name=赵六, classes=002, score1=66, score2=86.0, type=1)
1.2 取某一个字段生成新的List
@Test
public void test01(){
List<Student> studentList = getList();
// 1、取list中每个item的name字段组成新的list
List<String> collect = studentList.stream()
.map(Student::getName)
.collect(Collectors.toList());
System.out.println("collect = " + collect);
}
打印结果:(点击左侧小三角显示)====================================>
collect = [张三, 李四, 王五, 赵六, 齐七]
1.3 去重
/**
* 去重
*/
@Test
public void test02(){
List<String> listStr = getListStr();
System.out.println("去重前 = " + listStr);
listStr = listStr.stream().distinct().collect(Collectors.toList());
System.out.println("去重后=" + listStr);
}
打印结果:(点击左侧小三角显示)====================================>
去重前 = [A, C, B, C]
去重后 = [A, C, B]
1.4 排序
@Test
public void test01(){
List<Student> studentList = getList();
// 1、取list中每个item的name字段组成新的list
List<String> collect = studentList.stream()
.map(Student::getName)
.collect(Collectors.toList());
System.out.println("collect = " + collect);
}
打印结果:(点击左侧小三角显示)====================================>
student = Student(name=齐七, classes=003, score1=68, score2=88.0, type=2)
student = Student(name=赵六, classes=002, score1=66, score2=86.0, type=1)
student = Student(name=王五, classes=002, score1=64, score2=84.0, type=0)
student = Student(name=李四, classes=001, score1=62, score2=82.0, type=0)
student = Student(name=张三, classes=001, score1=60, score2=80.0, type=0)
1.5 过滤
/**
* 过滤 -- 根据List过滤班级(简单使用可以)
*/
@Test
public void test04(){
// 过滤出classes=001和003的学生
ArrayList<String> list = new ArrayList<>();
list.add("001");
list.add("003");
List<Student> studentList = getList();
List<Student> collect = studentList.stream()
.filter(student -> student.getClasses().equals("001"))
.collect((Collectors.toList()));
for (Student student : collect) {
System.out.println("student = " + student);
}
System.out.println("--------------- 分割线 ---------------");
List<Student> collect1 = studentList.stream()
.filter(student -> list.contains(student.getClasses()))
.collect(Collectors.toList());
for (Student student1 : collect1) {
System.out.println("student1 = " + student1);
}
}
打印结果:(点击左侧小三角显示)====================================>
student = Student(name=张三, classes=001, score1=60, score2=80.0, type=0)
student = Student(name=李四, classes=001, score1=62, score2=82.0, type=0)
--------------- 分割线 ---------------
student1 = Student(name=张三, classes=001, score1=60, score2=80.0, type=0)
student1 = Student(name=李四, classes=001, score1=62, score2=82.0, type=0)
student1 = Student(name=齐七, classes=003, score1=68, score2=88.0, type=2)
1.6 分组
/**
* 分组
*/
@Test
public void test05(){
List<Student> studentList = getList();
//简单分组 -- 以班级作为分组条件
Map<String, List<Student>> collect = studentList.stream().collect(Collectors.groupingBy(Student::getClasses));
collect.forEach((key, value) -> {
System.out.println("当前班级: [" + key + "], 当前value: " + JSON.toJSONString(value));
});
System.out.println("--------------- 分割线 ---------------");
//嵌套分组 -- 以班级作为分组条件后再以type分组
Map<String, Map<Integer, List<Student>>> collect1 = studentList.stream()
.collect(Collectors.groupingBy(
Student::getClasses,
Collectors.groupingBy(Student::getType)
)
);
collect1.forEach((key, value) -> {
value.forEach((key1, value2) -> {
System.out.println("当前班级: [" + key + "], 当前type: [" + key1 +"] " + JSON.toJSONString(value2));
});
});
}
打印结果:(点击左侧小三角显示)====================================>
当前班级: [001], 当前value: [{“classes”:“001”,“name”:“张三”,“score1”:60,“score2”:80.0,“type”:0},{“classes”:“001”,“name”:“李四”,“score1”:62,“score2”:82.0,“type”:0}]
当前班级: [002], 当前value: [{“classes”:“002”,“name”:“王五”,“score1”:64,“score2”:84.0,“type”:0},{“classes”:“002”,“name”:“赵六”,“score1”:66,“score2”:86.0,“type”:1}]
当前班级: [003], 当前value: [{“classes”:“003”,“name”:“齐七”,“score1”:68,“score2”:88.0,“type”:2}]
--------------- 分割线 ---------------
当前班级: [001], 当前type: [0] [{“classes”:“001”,“name”:“张三”,“score1”:60,“score2”:80.0,“type”:0},{“classes”:“001”,“name”:“李四”,“score1”:62,“score2”:82.0,“type”:0}]
当前班级: [002], 当前type: [0] [{“classes”:“002”,“name”:“王五”,“score1”:64,“score2”:84.0,“type”:0}]
当前班级: [002], 当前type: [1] [{“classes”:“002”,“name”:“赵六”,“score1”:66,“score2”:86.0,“type”:1}]
当前班级: [003], 当前type: [2] [{“classes”:“003”,“name”:“齐七”,“score1”:68,“score2”:88.0,“type”:2}]
二、stream进阶玩法
2.1 列求和
/**
* List 列求和
* 对score1、score2 求和
*/
@Test
public void test06(){
List<Student> studentList = getList();
// 方式1
Student student = studentList.stream().reduce(new Student(0, 0d), (s1, s2) ->
new Student(s1.getScore1() + s2.getScore1(), s1.getScore2() + s2.getScore2())
);
System.out.println("student = " + student);
System.out.println("--------------- 分割线 ---------------");
// 方式2
// 假如求和字段同类型
int[] reduce = studentList.stream().reduce(new int[]{0, 0},
(result, student1) -> new int[]{result[0] + student1.getScore1(), (int) (result[1] + student1.getScore2())},
(result1, result2) -> new int[]{result1[0] + result2[2], result1[1] + result2[1]});
System.out.println("reduce = " + Arrays.toString(reduce));
}
打印结果:(点击左侧小三角显示)====================================>
student = Student(name=null, classes=null, score1=320, score2=420.0, type=null)
--------------- 分割线 ---------------
reduce = [320, 420]
2.2 flatMap使用
/**
* flatMap 把每个item为一个流,然后再汇总
*/
@Test
public void test07(){
List<String> sentences = Arrays.asList("Hello World", "Java Stream Example", "FlatMap Usage");
List<String> words = sentences.stream()
.map(sentence -> sentence.split(" ")) // 将句子拆分为单词数组
.flatMap(Arrays::stream) // 将每个单词数组映射为一个流,并将这些流合并成一个新的流
.collect(Collectors.toList()); // 将合并后的单词流收集为列表
System.out.println("words = " + words);
}
打印结果:(点击左侧小三角显示)====================================>
words = [Hello, World, Java, Stream, Example, FlatMap, Usage]
完整代码如下:
import com.alibaba.fastjson2.JSON;
import com.me.domain.Student;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@SpringBootTest
public class StreamTest {
// ============================ stream基础 ==================================
/**
* 1、取List中每个item的某一个字段
* 2、list转map name作为key, value为student
*/
@Test
public void test01(){
List<Student> studentList = getList();
// 1、取list中每个item的name字段组成新的list
List<String> collect = studentList.stream()
.map(Student::getName)
.collect(Collectors.toList());
System.out.println("collect = " + collect);
// 2、list转map name作为key, value为student
Map<String, Student> studentMap = studentList.stream()
.collect(Collectors.toMap(Student::getName, student -> student));
studentMap.forEach((k, v) ->{
System.out.println("k=" + k + ", v=" + v.toString());
});
}
/**
* 去重
*/
@Test
public void test02(){
List<String> listStr = getListStr();
System.out.println("去重前 = " + listStr);
listStr = listStr.stream().distinct().collect(Collectors.toList());
System.out.println("去重后=" + listStr);
}
/**
* 排序 -- 根据student的score1降序
*/
@Test
public void test03(){
List<Student> studentList = getList();
List<Student> collect = studentList.stream()
.sorted((s1, s2) -> s2.getScore1() - s1.getScore1())
.collect(Collectors.toList());
for (Student student : collect) {
System.out.println("student = " + student);
}
}
/**
* 过滤 -- 根据List过滤班级(简单使用可以)
*/
@Test
public void test04(){
// 过滤出classes=001和003的学生
ArrayList<String> list = new ArrayList<>();
list.add("001");
list.add("003");
List<Student> studentList = getList();
List<Student> collect = studentList.stream()
.filter(student -> student.getClasses().equals("001"))
.collect((Collectors.toList()));
for (Student student : collect) {
System.out.println("student = " + student);
}
System.out.println("--------------- 分割线 ---------------");
List<Student> collect1 = studentList.stream()
.filter(student -> list.contains(student.getClasses()))
.collect(Collectors.toList());
for (Student student1 : collect1) {
System.out.println("student1 = " + student1);
}
}
/**
* 分组
*/
@Test
public void test05(){
List<Student> studentList = getList();
//简单分组 -- 以班级作为分组条件
Map<String, List<Student>> collect = studentList.stream().collect(Collectors.groupingBy(Student::getClasses));
collect.forEach((key, value) -> {
System.out.println("当前班级: [" + key + "], 当前value: " + JSON.toJSONString(value));
});
System.out.println("--------------- 分割线 ---------------");
//嵌套分组 -- 以班级作为分组条件后再以type分组
Map<String, Map<Integer, List<Student>>> collect1 = studentList.stream()
.collect(Collectors.groupingBy(
Student::getClasses,
Collectors.groupingBy(Student::getType)
)
);
collect1.forEach((key, value) -> {
value.forEach((key1, value2) -> {
System.out.println("当前班级: [" + key + "], 当前type: [" + key1 +"] " + JSON.toJSONString(value2));
});
});
}
// ============================ stream进阶玩法 ==================================
/**
* List 列求和
* 对score1、score2 求和
*/
@Test
public void test06(){
List<Student> studentList = getList();
// 方式1
Student student = studentList.stream().reduce(new Student(0, 0d), (s1, s2) ->
new Student(s1.getScore1() + s2.getScore1(), s1.getScore2() + s2.getScore2())
);
System.out.println("student = " + student);
System.out.println("--------------- 分割线 ---------------");
// 方式2
// 假如求和字段同类型
int[] reduce = studentList.stream().reduce(new int[]{0, 0},
(result, student1) -> new int[]{result[0] + student1.getScore1(), (int) (result[1] + student1.getScore2())},
(result1, result2) -> new int[]{result1[0] + result2[2], result1[1] + result2[1]});
System.out.println("reduce = " + Arrays.toString(reduce));
}
/**
* flatMap 把每个item为一个流,然后再汇总
*/
@Test
public void test07(){
List<String> sentences = Arrays.asList("Hello World", "Java Stream Example", "FlatMap Usage");
List<String> words = sentences.stream()
.map(sentence -> sentence.split(" ")) // 将句子拆分为单词数组
.flatMap(Arrays::stream) // 将每个单词数组映射为一个流,并将这些流合并成一个新的流
.collect(Collectors.toList()); // 将合并后的单词流收集为列表
System.out.println("words = " + words);
}
public List<Student> getList(){
List<Student> studentList = new ArrayList<>(5);
Student student1 = new Student("张三", "001", 60, 80d, 0);
Student student2 = new Student("李四", "001", 62, 82d, 0);
Student student3 = new Student("王五", "002", 64, 84d, 0);
Student student4 = new Student("赵六", "002", 66, 86d, 1);
Student student5 = new Student("齐七", "003", 68, 88d, 2);
studentList.add(student1);
studentList.add(student2);
studentList.add(student3);
studentList.add(student4);
studentList.add(student5);
return studentList;
}
public List<String> getListStr(){
List<String> list = new ArrayList<>();
list.add("A");
list.add("C");
list.add("B");
list.add("C");
return list;
}
}