7

我要排序CopyOnWriteArrayList。但是当我尝试运行以下代码时

它在投掷unsorted operation exception

public class CopyOnWriteArrayListExample {

  public static void main(final String[] args) {
     List<String> list = new CopyOnWriteArrayList<>();
    list.add("3");
    list.add("2");
    list.add("1");

    Collections.sort(list);
   }
}

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049)
at java.util.Collections.sort(Collections.java:159)
at com.sac.list.CopyOnWriteArrayListExample.main(CopyOnWriteArrayListExample.java:15)  

提前致谢。

4

5 回答 5

11

Collections.sort 使用 ListIterator.set

    ...
    for (int j=0; j<a.length; j++) {
        i.next();
        i.set((T)a[j]);
    }

但是 CopyOnWriteArrayList 的 ListIterator 不支持 remove、set 或 add 方法。

解决方法:

    Object[] a = list.toArray();
    Arrays.sort(a);
    for (int i = 0; i < a.length; i++) {
        list.set(i, (String) a[i]);
    }
于 2015-03-02T08:34:20.903 回答
6

Evgeniy 的解决方案指向正确,但list.set(i, (String) a[i])必须锁定list列表中的每个元素。如果有一个并发线程写入list这个将显着减慢循环。

为了尽量减少阻塞,最好减少改变的语句数量list

    CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

    // ... fill list with values ...

    ArrayList<Integer> temp = new ArrayList<>();
    temp.addAll(list);                           
    Collections.sort(temp);

    list.clear();            // 1st time list is locked
    list.addAll(temp);       // 2nd time list is locked

不利的一面是,如果一个并发线程list在两者之间读取clear()addAll(temp)它将看到一个空列表,而使用 Evgeniy 的解决方案它可能会看到一个部分排序的列表。

于 2017-05-11T12:47:30.147 回答
6

在JDK1.8可以sort(Comparator<? super E> c)直接使用。

List<Integer> list = new CopyOnWriteArrayList<Integer>();

list.add(3);
list.add(4);
list.add(1);

list.sort(new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1 - o2;
    }
});
于 2017-08-16T12:38:12.867 回答
1

因为每次更改时 CopyOnWriteArrayList 都会复制自身,因此它的 Iterator 不允许您更改列表。如果是这样,Iterator 就不是线程安全的,而线程安全是这个类的重点。Collections.sort()不起作用,因为它需要一个支持该set()方法的迭代器。

于 2015-03-02T08:28:48.343 回答
0

Kotlin 辅助函数

inline fun <T, R : Comparable<R>> CopyOnWriteArrayList<T>.sortListBy(crossinline selector: (T) -> R?) {
    if (size > 1) {
        val list = ArrayList(this)
        list.sortBy(selector)
        clear()
        addAll(list)
    }
}

在安卓上

inline fun <T, R : Comparable<R>> CopyOnWriteArrayList<T>.sortListBy(crossinline selector: (T) -> R?) {
    if (size > 1) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sortBy(selector)
        } else {
            val list = ArrayList(this)
            list.sortBy(selector)
            clear()
            addAll(list)
        }
    }
}
于 2020-04-01T10:30:23.747 回答