1.为什么有这门技术
在我发现这门技术之前,我对列表的操作都是使用 for 循环进行处理的,代码冗余,非常不美观。尤其时涉及到两个列表的时候,可能会使用到 for 循环的嵌套来进行逻辑处理,导致时间和空间复杂度非常高。而且涉及到的逻辑非常复杂,难以理解和维护。
2.这门技术解决了什么问题
我当时准备从一堆数据库查询出来的数据和另一堆请求传递上来的数据进行比较,决定哪些数据需要新增,哪些需要更新,哪些需要删除。最初我使用的是 map,将数据库查询出来的数据先遍历,按照需要比对的条件进行组装,并且将value初始化为false。再对请求传递上来的列表进行遍历,按照条件在映射中查找,如果找到了就更新,并且将value改为true,如果没找到就新增。最后对map 进行遍历,将所有value值为false的从数据库中删除。
以学生信息为例,代码如下。
//学生信息数据库操作服务
@Autowired
StudentService studentService;
//维护学生信息请求
ModifyStudentRequest request;
//业务处理方法
public void doProcess(){
//查询数据库得到的列表
List<Student> studentList = studentService.listStudent;
//请求的学生信息列表
List<AnotherStudent> anoStudentList = request.getStudentList();
//储存信息的映射
Map<String, Boolean> studentMap = new HashMap<>();
//如果数据库学生列表不为空,则组装到映射中。布尔值为false表示删除,true表示更新
if(studentList != null && studentList.size > 0){
for(Student student : studentList){
studentMap.put(student.getName(), false);
}
}
if(anoStudentList != null && anoStudentList.size > 0){
//对请求的学生列表进行遍历
for(AnotherStudent anoStudent : anoStudentList){
Student param = new Student();
param.setName(anoStudent.getName());
param.setAge(anoStudent.getAge);
//如果在学生姓名在数据库中存在,则更新
if(studentMap.containsKey(anoStudent.getName())){
studentService.updateStudent(param);
//将映射中对应的布尔值改为true,之后不会被删除
studentMap.replace(param.getName(), true)
}//如果不存在则新增
else {
studentService.saveStudent(param);
}
}
}
if(studentMap != null){
//对映射进行遍历,如果value值为false,则从数据库中删除
for(Map.Entry<String, Boolean> entry : studentMap.entrySet()){
if(entry.getValue() == false){
Student param = new Student();
param.setName(entry.getKey());
studentService.deleteStudent(param);
}
}
}
}
可以看出,代码有很多的 if 和 for 逻辑相互嵌套,十分复杂。在使用了 stream 流之后,代码变得简洁,可读性大大提高。
3.使用 steam 处理 list 列表
首先,需要解决如下几个问题
1.使用 stream 的时候,在条件判断的时候,使用的是 列表自带的 contains 方法,以 ArrayList 为例,此方法的底层是使用列表元素自身的equals 方法。所以在进行判断之前,需要先对元素的equals方法进行重写。
2.我在使用的时候,尝试了两个列表不同元素类型的情况下进行比较,但是因为equals方法的现在,没有成功,所以我使用 stream 将他们转换成了相同元素类型,再进行的比较。
3.在对数据库操作时,使用了并行流。
还以学生信息为例,代码如下:
//学生信息数据库操作服务
@Autowired
StudentService studentService;
//维护学生信息请求
ModifyStudentRequest request;
//业务处理方法
public void doProcess(){
//查询数据库得到的列表
List<Student> studentList = studentService.listStudent;
//请求的学生信息列表
List<AnotherStudent> anoStudentList = request.getStudentList();
//将BlsPartsItem类型的列表转换成PartsItemVO类型的列表
List<AnotherStudent> newStudentList = studentList.stream()
.map(e -> new AnotherStudent(e.getName(), e.getAge()))
.collect(Collectors.toList());
//获取需要更新列表
List<AnotherStudent> updateList = anoStudentList.stream().filter(item -> newStudentList.contains(item)).collect(Collectors.toList());
//获取需要新增列表
List<AnotherStudent> saveList = anoStudentList.stream().filter(item -> !newStudentList.contains(item)).collect(Collectors.toList());
//获取需要删除列表
List<AnotherStudent> deleteList = newStudentList.stream().filter(item -> !anoStudentList.contains(item)).collect(Collectors.toList());
Student param = new Student();
//更新数据库
updateList.stream().parallel().forEach(anoStudent -> {
param.setName(anoStudent.getName());
param.setAge(anoStudent.getAge);
studentService.update(param);
});
//新增数据库
saveList.stream().parallel().forEach(anoStudent -> {
param.setName(anoStudent.getName());
param.setAge(anoStudent.getAge);
studentService.save(param);
});
//删除数据库
deleteList.stream().parallel().forEach(anoStudent -> {
param.setName(anoStudent.getName());
param.setAge(anoStudent.getAge);
studentService.delete(param);
});
}
这样去掉了很多 if 和 for 的逻辑,整体逻辑更加清晰,在对数据库操作的时候使用了并行流,加快了响应速度。