JDK1.8新特性将List转换为Map

 

在开发中经常会遇到将List<T>转换为Map<R,List<T>>的问题。

如存在多对一关联的学生表与班级表(在学生表中关联班级ID)中有如下需求:

查询每个班级下的所有学生,将学生姓名打印出来。(将学生按班级分组后打印学生姓名)

学生实体

/**
 * 学生表
 * @author dirk
 *
 */
public class Student {
	/**
	 * id
	 */
	private String id;
	/**
	 * 姓名
	 */
	private String name;
	/**
	 * 班级id
	 */
	private String classId;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassId() {
		return classId;
	}
	public void setClassId(String classId) {
		this.classId = classId;
	}
	
	/**
	 * 测试使用
	 * @return 测试数据
	 */
	public static List<Student> createShortList() {
		List<Student> studentList = new ArrayList<Student>();
		Student s1 = new Student();
		s1.setId("1");
		s1.setName("小A");
		s1.setClassId("20");
		studentList.add(s1);
		Student s2 = new Student();
		s2.setId("2");
		s2.setName("小B");
		s2.setClassId("40");
		studentList.add(s2);
		Student s3 = new Student();
		s3.setId("3");
		s3.setName("小C");
		s3.setClassId("20");
		studentList.add(s3);
		Student s4 = new Student();
		s4.setId("4");
		s4.setName("小D");
		s4.setClassId("30");
		studentList.add(s4);
		Student s5 = new Student();
		s5.setId("5");
		s5.setName("小E");
		s5.setClassId("40");
		studentList.add(s5);
		Student s6 = new Student();
		s6.setId("6");
		s6.setName("小F");
		s6.setClassId("20");
		studentList.add(s6);
		return studentList;
	}
}	

最简单的方式为先将班级查询出来,然后遍历班级再查询每个班级下的学生。这种做法最大的缺点是与数据库操作过于多,影响效率(班级越多效率越低)。

为了减少与数据库的操作,可以一次将所有的学生全部查询出来,得到List<Student>对象,然后遍历此集合按班级进行分组。

1)、传统方式:遍历学生集合,按班级进行分组

public static void main(String[] args) {
    // 得到待转换的List
    // 生产环境中从数据库中查出
    List<Student> studentList = Student.createShortList();
		
    // 将studentList按班级进行分组
    // 转换后的结果,key值为班级id,value为该班级下的学生集合
    Map<String, List<Student>> studentMap = new HashMap<String, List<Student>>();
		
    // 循环studentList进行分组
    for (Student student : studentList) {
        // 得到所有班级
	    String classId = student.getClassId();
	    // 判断此classId在Map中是否存在
	    List<Student> resultList = studentMap.get(classId);
	    // map中不存在,则初始化一个list放到map中
	    if (resultList==null) {
		    resultList = new ArrayList<Student>();
		    studentMap.put(classId, resultList);
	    }
	    // 将学生加入到班级所在的集合中
	    resultList.add(student);
    }
		
    // 输出结果判断结果是否正确
    studentMap.forEach((k,v) -> {
        String studentNames = v.stream().map(l -> l.getName()).collect(Collectors.joining(","));
        System.out.println("班级【"+k+"】下的学生姓名为【"+studentNames+"】");
    });
}

2)、使用JDK8新特性(函数式编程)(推荐)

public static void main(String[] args) {
    // 得到待转换的List
    // 生产环境中从数据库中查出
    List<Student> studentList = Student.createShortList();
		
    // 使用函数式编程方法,直接按班级进行分组
    Map<String, List<Student>> studentMap = studentList.stream().collect(Collectors.groupingBy(Student::getClassId));
		
    // 输出结果判断结果是否正确
    studentMap.forEach((k,v) -> {
        String studentNames = v.stream().map(l -> l.getName()).collect(Collectors.joining(","));
	System.out.println("班级【"+k+"】下的学生姓名为【"+studentNames+"】");
    });
}
​

发表评论

电子邮件地址不会被公开。 必填项已用*标注