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

Tum*_*Tum 11 java collections java-7 java-8

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

CopyOnWriteArrayList<User> allCurrentLoginnedUsersList = new CopyOnWriteArrayList<>(); 
Collections.sort(allCurrentLoginnedUsersList);
Run Code Online (Sandbox Code Playgroud)

现在,我改为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)
Run Code Online (Sandbox Code Playgroud)

怎么解决?

Tun*_*aki 15

Java 7(和早期版本的Java 8)和Java 8u20在Collections.sort工作方式上有所变化(问题8032636,如Holger所述).


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

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

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

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

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


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

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

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