stream流实战应用
基础应用看 stream流基础应用
1.stream流把数组列表转为实体类列表
通过map方法去每一次循环做操作
(map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。)
List<Object[]> students = studentService.findByAgeList(ageList);
List<Student> student = students.stream()
.map(item -> {
Student student= new Student();
student.setName((String) item[0]);
student.setId((String) item[1]);
student.setAge((String) item[2]);
return student;
})
.collect(Collectors.toList());
2.stream流按照属性进行分组/排序
Collectors.groupingBy()方法进行分组,Comparator.comparing()方法是对分组结果进行排序,也就是age属性
Map<Object, List<Student>> tempMap = new LinkedHashMap<>();
tempMap = student.parallelStream()
.sorted(Comparator.comparing(Student::getAge))
.collect(Collectors.groupingBy(Student-> Student.getAge()));
另一种
List<Map<String,Object>> authorList = new ArrayList<>();
authorList .sort(Comparator.comparing(map -> {
String age = map.get("age").toString();
return Integer.parseInt(age);
}));
3.filter()筛选
String s = authorList.stream().filter(item -> item.getName().equals(authorName))
.findFirst().map(StudentEntity::getId).orElse("null");
筛选出相等的元素,findFirst()取第一个元素,orElse()是如果取不到数据就给它赋默认你填写的值
*这个里可能会出现一个问题,我之前是把findFirst()放到了map的后边,但是因为getId可能是空,取不到值就会报空指针,所以移到了前面,根据具体情况去看你需要什么样的一个stream流
stuList.stream()
.filter(item -> item.getName().equals(authorName))
.forEach(studentEntity-> studentEntity.setSid("accountSid"));
还可以给筛选出的指定数据进行循环赋值
4.isPresent()方法 判空
用于判空,返回Optional的情况下使用 true为存在
如果确定有数据的话可以直接在括号里写
first.ifPresent(content-> dataList.add(content.getName()));
5.count()方法 记录总数
记录总数
dataList.stream().filter(item -> item.getState() == 2).count()
6.sorted()方法 排序 和Comparator.comparingInt()
sorted()用于排序 Comparator.comparingInt()返回结果转为int
List<Student> sortedStudentList = StudentInfoItemList() .stream()
.sorted(Comparator.comparingInt(studentInfoItem ->
educService.findById(studentInfoItem.getEducId()).getLevel()))
.toList();
7. anyMatch()方法 存在筛选的数据
是否存在筛选后的数据
boolean exist = sortedEducList.stream()
.anyMatch(item -> educService.findBySid(item.getEducId())
.getLevel() >= stuLevel);
注:一个stream流只能使用一次,也就是返回的Stream流只能在被操作一次,用过之后流就不存在了
8.sum()方法求和
int sum = dataMap.stream()
.mapToInt(item -> Integer.parseInt(item.get("count"))).sum();
8.优化stream流的运行速度
将普通的steam流变成并行流(parallelStream)对于可以并行处理的部分
List<Object[]> students = studentService.findByAgeList(ageList);
List<Student> student = students.parallelStream()
.map(item -> {
Student student= new Student();
student.setName((String) item[0]);
student.setId((String) item[1]);
student.setAge((String) item[2]);
return student;
})
.collect(Collectors.toList());
并行流使用的相关
1.概念
并行流是Java 8引入的一种流处理方式,可以在多个线程上同时执行操作,以提高处理速度。它适用于那些可以独立处理的操作,每个操作之间没有依赖关系。
然而,并行流在处理数据时会使用多个线程并发执行操作,因此可能存在并发问题。当多个线程同时修改共享的数据时,可能会导致数据不一致或产生其他问题。
为了避免并发问题,在使用并行流时需要确保对共享数据的访问是线程安全的,或者通过使用线程安全的集合类来避免共享数据的修改。例如,可以使用Collectors.groupingByConcurrent()
方法来创建一个线程安全的Map,或者使用并发集合类如ConcurrentHashMap
。
此外,还需要注意在使用并行流时,一些操作可能会失去顺序性。并行流会对数据进行分区处理,并且每个分区都可能在不同的线程上执行操作,所以最终的处理结果可能会失去原有的顺序。如果需要保持顺序,可以使用forEachOrdered()
方法来替代forEach()
方法。
总之,在使用并行流时需要确保数据访问的线程安全性,并且考虑到并发问题和顺序性的影响。
2.操作主要是查询和数据转换
如果代码中的操作主要是查询和数据转换,并且没有直接修改共享数据的部分,那么这个代码片段可能没有并发问题。
在这种情况下,使用并行流可以提高代码的执行效率,因为查询和转换操作是独立的,并且没有共享数据的修改。并行流可以将这些操作并行地分配给多个线程,以加快处理速度。
然而,仍然建议在使用并行流时谨慎考虑以下几点:
- 查询操作是否与外部资源(如数据库)有关。如果查询操作涉及到对共享资源的读取或写入,需要确保对共享资源的访问是线程安全的。
- 数据转换操作是否引入了状态变化。如果数据转换操作依赖于其他操作的结果或状态,可能会导致并发问题。确保操作之间的依赖关系被正确处理。
- 并行流在某些情况下可能导致额外的开销。在数据量较小或处理逻辑简单的情况下,并行流可能不一定比顺序流更快。在实际使用中,可以尝试使用不同的流类型进行比较和性能测试,找到最合适的方式。
总之,如果你的代码只涉及查询和数据转换,并且没有直接修改共享数据,那么在大多数情况下,使用并行流是安全且高效的。但仍建议对代码进行充分测试和验证,以确保并行流的正确性和性能提升。