繁体   English   中英

为什么Collections.sort(List)在Java 8中使用CopyOnWriteArrayList但在Java 7中不起作用?

[英]Why does Collections.sort(List) work in Java 8 with CopyOnWriteArrayList but not in Java 7?

我可以使用以下代码和Java 8对用户列表进行排序而没有任何问题:

CopyOnWriteArrayList<User> allCurrentLoginnedUsersList = new CopyOnWriteArrayList<>(); 
Collections.sort(allCurrentLoginnedUsersList);

现在,我改为Java 7,我在eclipse上看到没有错误。 但是现在,在Java 7下运行时出现了这个错误:

java.lang.UnsupportedOperationException
    at java.util.concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049)
    at java.util.Collections.sort(Collections.java:221)
    at com.fluent.User.sortAllCurrentLoginnedUsers(User.java:446)

怎么解决?

Java 7(和早期版本的Java 8)和Java 8u20之间的Collections.sortCollections.sort的方式发生了变化( 问题8032636 ,如Holger所述 )。


Java 7 Collections.sort(list, c)指定:

此实现将指定的列表转储到数组中,对数组进行排序,并迭代列表,从数组中的相应位置重置每个元素。 这样可以避免尝试对链接列表进行排序所导致的n²log(n)性能。

查看代码 ,这是通过从列表中获取ListIterator来完成的。 但是, CopyOnWriteArrayList listIterator()方法声明返回的迭代器不支持set操作:

返回的迭代器提供构造迭代器时列表状态的快照。 遍历迭代器时不需要同步。 迭代器不支持removesetadd方法

这解释了使用Java 7运行代码时出现的错误。作为一种解决方法,您可以参考这个问题 ,其中的答案是将列表的内容转储到数组中,对数组进行排序并将元素放回到名单。


在Java 8中, Collections.sort(list, c)改变了实现:

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

新方法CopyOnWriteArrayList.sort(c) (在Java 8中引入)不使用列表迭代器,因此它可以正常工作。

Java 7中的Collections.sort() (以及Java 8的早期版本)使用列表迭代器的set()来修改列表。 但是CopyOnWriteArrayList的迭代器被明确记录为不支持此操作。

怎么解决? CopyOnWriteArrayList转换为常规ArrayList或数组,对其进行排序,然后清除CopyOnWriteArrayList并使用排序列表再次填充它。

我强烈建议使用Integer.compare()Boolean.compare()使比较器更简单。

在Java 8中, Collections.sort(List, Comparator)的实现已更改为现在重定向到List接口中sort方法 sort方法的默认实现似乎是先前的行为(即使用List.listIterator() ,它仍然会因UnsupportedOperationException而失败),但CopyOnWriteArrayList显式提供了不使用Iterator的不同版本:

public void sort(Comparator<? super E> c) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        Object[] newElements = Arrays.copyOf(elements, elements.length);
        @SuppressWarnings("unchecked") E[] es = (E[])newElements;
        Arrays.sort(es, c);
        setArray(newElements);
    } finally {
        lock.unlock();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM