问题描述
在实际开发中经常会有类似的这种代码,想要按类的某一个属性对列表中的元素分组。
例如:
有一些学生,然后根绝他们的年龄对他们进行分组。可以写出如下代码。
public class UnsupportedOperationExceptionDemo {@Data@NoArgsConstructor@AllArgsConstructorpublic static class Student {private String name;private Integer age;}public static void main(String[] args) {// 初始化几个学生List<Student> studentList = new ArrayList<>();studentList.add(new Student("张三", 18));studentList.add(new Student("李四", 19));studentList.add(new Student("王五", 18));studentList.add(new Student("赵六", 20));// 根据年龄对这个分组Map<Integer, List<Student>> map = new HashMap<>();for (Student student : studentList) {if (map.containsKey(student.getAge())) {List<Student> students = map.get(student.getAge());students.add(student);} else {map.put(student.getAge(), Arrays.asList(student));}}}
}
运行结果:
这是为什么呢?
原因分析
在for循环中如果集合中没有这个年龄的学生,则需要创建一个List然后将元素加入,所以偷了一下懒,直接使用了Arrays.asList(student)
这样的代码。
问题就出在这一行代码!!!!
看一下asList
的源码,发现也是new ArrayList(a)
不过仔细看一下这个ArrayList
的全限定名是java.util.Arrays.ArrayList
而不是我们平常使用的java.util.ArrayList
那这两个有何不同?为什么会报错?
因为上面的代码调用了java.util.Arrays.ArrayList
对象的add
方法,这个类并没有重写add
方法,所以直接使用父类java.util.AbstractList
中的方法,而父类的add
方法就是会抛出UnsupportedOperationException
异常
解决方案
方案一:创建java.util.ArrayList
对象来存放元素
方案二:使用Java 8的Stream流来处理
Map<Integer, List<Student>> map = studentList.stream().collect(Collectors.groupingBy(Student::getAge));