How to sort CopyOnWriteArrayList

Collections.sort uses ListIterator.set

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

but CopyOnWriteArrayList's ListIterator does not support the remove, set or add methods.

Workaround:

    Object[] a = list.toArray();
    Arrays.sort(a);
    for (int i = 0; i < a.length; i++) {
        list.set(i, (String) a[i]);
    }

Evgeniy's solution points in the right way, but list.set(i, (String) a[i]) has to gain the lock on list for each element in the list. If there is a concurrent thread which writes into list this will slow down the loop dramatically.

To minimize blocking it's better to reduce the number of statements which alter 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

The downside is that if a concurrent thread reads list between clear() and addAll(temp) it will see an empty list wheras with Evgeniy's solution it may see a partially sorted list.


In JDK1.8 can use sort(Comparator<? super E> c) directly.

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;
    }
});