Выполнение операции сортировки для CopyOnArrayList приводит к java.lang.UnsupportedOperationException
Чтобы избежать исключения модификации параллельного потока, я использовал CopyOnArrayList и позже, когда попытался отсортировать этот список с помощью метода сортировки класса Collection, что привело к следующему исключению:-
Исключение в потоке "main" java.lang.UnsupportedOperationException
В результате я попытался прочитать Javadoc, доступный для CopyOnArrayList
который говорит
Операции изменения элементов на самих итераторах (удаление, установка и добавление) не поддерживаются. Эти методы генерируют исключение UnsupportedOperationException.
Но, как я понимаю, сортировка в любом смысле требует добавления и удаления элементов во временные списки. Но почему это воздерживается? Он работает на клонировании объектов, так что этот фактор влияет никак.
Тестовый код:
package test;
import java.util.Comparator;
/**
*
* @author vaibhav.kashyap
*/
public class Student implements Comparator<Student>{
private String name = "";
private int age = -1;
public Student(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() <o2.getAge() ?-1:o1.getAge()==o2.getAge()?0:1;
}
}
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
/**
*
* @author vaibhav.kashyap
*/
public class Main {
List<Student> stuList = new CopyOnWriteArrayList<Student>();
public static void main(String ar[]){
List<Student> tempList = new Main().makeList();
Collections.sort(tempList, new Student());
for(Student s : tempList){
System.out.println(s.getAge());
}
}
public List<Student> makeList(){
Student stu = null;
Scanner sc = new Scanner(System.in);
for(int i=0 ; i<5; i++){
stu = new Student();
System.out.println("Enter name");
String name = sc.next();
stu.setName(name);
System.out.println("Enter age");
int age = sc.nextInt();
stu.setAge(age);
stuList.add(stu);
}
return stuList;
}
}
Вывод: run: введите имя a Введите возраст 12 Введите имя b Введите возраст 10 Введите имя c Введите возраст 05 Введите имя d Введите возраст 100 Введите имя e Введите возраст 01 Исключение в теме "main" java.lang.UnsupportedOperationException at java.util.concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049) в java.util.Collections.sort(Collections.java:221) в test.Main.main(Main.java:23) Результат Java: 1 BUILD SUCCESSFUL (всего время: 30 секунд)
Эта концепция всегда была неопределенной для меня. Любое подробное объяснение будет весьма заметно.
1 ответ
Проблема в том, что Collections.sort() работает за кулисами, получая ListIterator для сортировки списка. Затем он использует метод set() этого итератора для внесения изменений, и, как указывает Javadoc, COWIterators не поддерживают операции изменения.
Почему бы не заставить CopyOnWriteArrayList реализовать собственный метод сортировки? Как сказал Джошуа Блох в этом интересном разговоре о проблеме сортировки этих списков, "нарушается совместимость добавления метода к широко реализуемому интерфейсу, такому как List, поэтому это невозможно". Кроме того, итераторам CopyOnWriteArrayLists не разрешается вносить изменения в базовые списки (IMHO), поскольку модификации в этих списках ОЧЕНЬ дороги. Изменение их настолько сильно, насколько требуется для сортировки, всегда должно быть тщательно продуманным решением, которое (к сожалению) не поддерживается изначально.