выполнение операции сортировки над CopyOnArrayList приводит к исключению java.lang.UnsupportedOperationException

Чтобы избежать исключения модификации параллельного потока, я использовал CopyOnArrayList и позже, когда пытался отсортировать этот список с помощью метода сортировки класса Collection, что привело к следующему исключению: -

Исключение в потоке "основной" 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 в java.util. concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049) в java.util.Collections.sort(Collections.java:221) в test.Main.main(Main.java:23) Результат Java: 1 УСПЕШНО ПОСТРОИТЬ (всего время: 30 секунд)

Это понятие всегда было для меня расплывчатым. Любое подробное объяснение будет весьма ценным.


person codechefvaibhavkashyap    schedule 12.11.2014    source источник


Ответы (1)


Проблема в том, что Collections.sort() работает за кулисами, получая ListIterator для сортировки списка. Затем он использует метод set() этого итератора для внесения изменений, и, как указывает Javadoc, COWIterators не поддерживают операции модификации.

Почему бы не заставить CopyOnWriteArrayList реализовать собственный метод сортировки? Как сказал Джошуа Блох в этом интересном разговоре о проблема сортировки этих списков: «Добавление метода в широко реализованный интерфейс, такой как List, нарушает совместимость, поэтому это невозможно». Кроме того, итераторам CopyOnWriteArrayLists не разрешено вносить изменения в базовые списки (ИМХО), потому что модификации в этих списках ОЧЕНЬ дороги. Изменение их так сильно, как требует сортировка, всегда должно быть тщательно обдуманным решением, которое (к сожалению) не поддерживается изначально.

person newcoder    schedule 12.11.2014
comment
Эта совместимость является причиной того, что в Java 8 были введены методы по умолчанию для интерфейсов, поэтому List теперь имеет метод сортировки, который действительно работает с CopyOnWriteArrayLists. - person VGR; 12.11.2014
comment
@newcoder спасибо, что было хорошо структурировано и частично объяснило контекст. - person codechefvaibhavkashyap; 14.11.2014