java 如何对CopyOnWriteArrayList进行排序?

lpwwtiir  于 2024-01-05  发布在  Java
关注(0)|答案(5)|浏览(237)

我想对CopyOnWriteArrayList进行排序。但是下面的代码抛出了一个UnsupportedOperationException

  1. public class CopyOnWriteArrayListExample {
  2. public static void main(final String[] args) {
  3. List<String> list = new CopyOnWriteArrayList<>();
  4. list.add("3");
  5. list.add("2");
  6. list.add("1");
  7. Collections.sort(list);
  8. }
  9. }

个字符
如何对CopyOnWriteArrayList进行排序?

9jyewag0

9jyewag01#

sort使用ListIterator.set

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

字符串
但CopyOnWriteArrayList的ListIterator不支持remove、set或add方法。
解决方法:

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

展开查看全部
pnwntuvh

pnwntuvh2#

Evgeniy的解决方案是正确的,但是list.set(i, (String) a[i])必须为列表中的每个元素获得list上的锁。如果有一个并发线程写入list,这将大大降低循环速度。
为了减少阻塞,最好减少改变list的语句的数量:

  1. CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
  2. // ... fill list with values ...
  3. ArrayList<Integer> temp = new ArrayList<>();
  4. temp.addAll(list);
  5. Collections.sort(temp);
  6. list.clear(); // 1st time list is locked
  7. list.addAll(temp); // 2nd time list is locked

字符串
缺点是,如果一个并发线程在clear()addAll(temp)之间读取list,它将看到一个空列表,而Evgeniy的解决方案可能会看到一个部分排序的列表。

zbwhf8kr

zbwhf8kr3#

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

  1. List<Integer> list = new CopyOnWriteArrayList<Integer>();
  2. list.add(3);
  3. list.add(4);
  4. list.add(1);
  5. list.sort(new Comparator<Integer>() {
  6. @Override
  7. public int compare(Integer o1, Integer o2) {
  8. return o1 - o2;
  9. }
  10. });

字符串

zynd9foi

zynd9foi4#

因为CopyOnWriteArrayList在每次你修改它的时候都会复制它自己,它的Iterator不允许你修改列表。如果它允许,Iterator就不是线程安全的,而线程安全是这个类的全部意义。Collections.sort()将不工作,因为它需要一个支持set()方法的Iterator。

6ioyuze2

6ioyuze25#

从Java 8开始,给定的代码无一例外地工作。
在Java 8之前的版本中,Collections.sort在给定列表的ListIterator上使用ListIterator.set,转发该方法抛出的任何UnsupportedOperationException

CopyOnWriteArrayList

不支持对迭代器本身(removesetadd)的元素更改操作。这些方法抛出UnsupportedOperationException
从Java 8开始,Collections.sort委托给新添加的List.sort方法。CopyOnWriteArrayList使用与之一起工作的自定义实现重写此方法。因此,Java 8版本的Collections.sort成功地对列表进行排序,而不是像Java的早期版本那样抛出异常。

Collections.sort
实施说明:

此实现遵循List.sort(Comparator)方法,使用指定的列表和比较器。

相关问题