![](/img/trans.png)
[英]How does Java's Collections.sort overwrite the List to be sorted
[英]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.sort
以Collections.sort
的方式发生了变化( 问题8032636 ,如Holger所述 )。
Java 7 Collections.sort(list, c)
指定:
此实现将指定的列表转储到数组中,对数组进行排序,并迭代列表,从数组中的相应位置重置每个元素。 这样可以避免尝试对链接列表进行排序所导致的n²log(n)性能。
查看代码 ,这是通过从列表中获取ListIterator
来完成的。 但是, CopyOnWriteArrayList
listIterator()
方法声明返回的迭代器不支持set
操作:
返回的迭代器提供构造迭代器时列表状态的快照。 遍历迭代器时不需要同步。 迭代器不支持
remove
,set
或add
方法 。
这解释了使用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.