tangguo

如何排序CopyOnWriteArrayList

java

我想排序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)  

提前致谢。


阅读 417

收藏
2020-11-20

共2个答案

小编典典

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]);
    }
2020-11-20
小编典典

叶夫根尼(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的解决方案,它将看到一个空列表,那么它可能会看到部分排序的列表。

2020-11-20