1.组装多个集合的数据,避免for循环操作数据库
假如有这样一个需求,需要我们组装从数据库中查出来的Student集合以及Student对应的班级名称返回给前端StudentVO
public static List<StudentVO> assembleData(List<Long> ids) { List<StudentVO> result = new ArrayList<>(); List<Student> students = this.selectBatchIds(ids); // 可能有小伙伴会用students的id一个个去数据库拿,但这样是不对的,会严重影响数据库性能 for (Person p : PersonList){ PersonVO vo = new PersonVO(); Class c = classMapper.selectById(p.getClassId()); p.setClassName(c.getName); result.add(p); } return result; }
循环访问数据库,是会严重影响数据库性能的
优化思路就是批量获取所有数据,然后再组装数据
public static List<StudentVO> assembleData(List<Long> ids) { //批量查出studnt List<Student> students = this.selectBatchIds(ids); //批量查出class 也可以写条sql,在sql语句循环查(效果比你for循环里查询数据库好) List<Long> classIds = students.stream().map(s -> s::getClassId()).distinct().collect(Collectors.toList()); List<Class> classes = classMapper.selectBatchIds(classIds); //转换成Map Map<String, Class> classMap = classes.stream().collect(Collectors.toMap(Class::getId, Function.identity())); //封装成StudentVO return s.stream().map(s -> { StudentVO vo = new StudentVO(); vo.setStudent(s); vo.setClassName(classes.get(s.getClassId()).getName()) return vo; }).collect(Collectors.toList()); }
sql参考模板
<select id="selectByUserIds" resultType="com.chenguangzhao.entities.UserInfoDTO" parameterType="java.util.List"> SELECT a.id AS userId, a.user_name AS userName, b.image_url AS imageUrl FROM t_user a LEFT JOIN t_image b on a.image_id=b.id <where> <if test="userIdList.size()>0"> a.id in <foreach collection="userIdList" item="id" index="index" open="(" close=")" separator=","> #{id} </foreach> </if> </where> </select>
2.把List转换为Map
public static Map<Long, Student> listToMap(List<Student> list) { return list.stream().collect(Collectors.toMap(Student::getId(), Function.identity())); }
3.按对象字段排序
public static List<Student> sortBy(List<Student> list) { return list.stream().sorted( (o1, o2) -> (o1.getId().compareTo(o2.getId())) ).collect(Collectors.toList()); } //简化 public static List<Student> sortBy(List<Student> list) { return list.stream().sorted( Comparator.comparing(Student::getId()) //直接调用类型内部实现的CompareTo ).collect(Collectors.toList()); } //倒序 public static List<Student> sortBy(List<Student> list) { return list.stream().sorted( Comparator.comparing(Student::getId()).reversed() ).collect(Collectors.toList()); } //多字段排序 public static List<Student> sortBy(List<Student> list) { return list.stream().sorted( Comparator.comparing(Student::getId()) .thenComparing(Student::getAge()) ).collect(Collectors.toList()); }
4.求多个集合的交集
public static List<Student> intersection(List<Student> s1, List<Student> s2) { Map<String, Student> m1 = s1.stream().collect(Collectors.toMap(Student::getId(), Function.identity())); return s2.stream().filter(s -> m1.get(s.getId())).collect(Collectors.toList()); }
5.把数据分组
在开发项目中我们可能会将从数据库中查出来的数据按照字段分组(其实在数据库中分好组也可以), 但是我们有时需要在业务层面输出
在Java8之前我们可能会这样写
public static Map<String, List<Student>> toGroupingMap(List<Student> list) { Map<String, List<Student>> resultMap = new Map<>(); for (Student s : list) { List<Student> students = resultMap.get(s.getAge()); if (students == null) { List<Student> s = new ArrayList<>(); resultMap.put(s.getAge(), s); } resultMap.put(s.getAge(), students); } }
Java8之后我们仅需要用stream分组函数就行了
public static Map<String, List<Student>> toGroupingMap(List<Student> list) { return list.stream().collect(Collectors.grouping(Student::getAge())); }