Java 如何对CopyOnWriteArrayList进行排序
我想对CopyOnWriteArrayList进行排序。但是当我尝试运行以下代码时 它正在引发Java 如何对CopyOnWriteArrayList进行排序,java,core,copyonwritearraylist,Java,Core,Copyonwritearraylist,我想对CopyOnWriteArrayList进行排序。但是当我尝试运行以下代码时 它正在引发未排序的操作异常 public class CopyOnWriteArrayListExample { public static void main(final String[] args) { List<String> list = new CopyOnWriteArrayList<>(); list.add("3"); list.add("2
未排序的操作异常
public class CopyOnWriteArrayListExample {
public static void main(final String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("3");
list.add("2");
list.add("1");
Collections.sort(list);
}
}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049)
at java.util.Collections.sort(Collections.java:159)
at com.sac.list.CopyOnWriteArrayListExample.main(CopyOnWriteArrayListExample.java:15)
public类copyonwritearrayliste示例{
公共静态void main(最终字符串[]args){
List List=新CopyOnWriteArrayList();
列表。添加(“3”);
列表。添加(“2”);
列表。添加(“1”);
集合。排序(列表);
}
}
线程“main”java.lang.UnsupportedOperationException中出现异常
位于java.util.concurrent.CopyOnWriteArrayList$coweditor.set(CopyOnWriteArrayList.java:1049)
位于java.util.Collections.sort(Collections.java:159)
位于com.sac.list.CopyOnWriteArrayListExample.main(CopyOnWriteArrayListExample.java:15)
提前感谢。因为CopyOnWriteArrayList会在每次更改时复制自身,所以它的迭代器不允许您对列表进行更改。如果是这样的话,迭代器就不会是线程安全的,线程安全是这个类的全部要点
Collections.sort()
不起作用,因为它需要一个支持set()
方法的迭代器。Collections.sort使用ListIterator.set
...
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
。。。
对于(int j=0;jEvgeniy的解决方案指向正确的方向,但是list.set(i,(String)a[i])
必须为列表中的每个元素锁定list
。如果存在写入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
CopyOnWriteArrayList list=new CopyOnWriteArrayList();
//…用值填充列表。。。
ArrayList temp=新的ArrayList();
临时添加所有(列表);
集合。排序(临时);
list.clear();//第一次锁定列表
list.addAll(temp);//第二次列表被锁定
缺点是,如果一个并发线程在clear()
和addAll(temp)
之间读取list
,它将看到一个空列表,而Evgeniy的解决方案可能会看到一个部分排序的列表。在JDK1.8中可以使用排序(ComparatorKotlin helper函数
inline fun <T, R : Comparable<R>> CopyOnWriteArrayList<T>.sortListBy(crossinline selector: (T) -> R?) {
if (size > 1) {
val list = ArrayList(this)
list.sortBy(selector)
clear()
addAll(list)
}
}
inline fun CopyOnWriteArrayList.sortListBy(交叉内联选择器:(T)->R?){
如果(大小>1){
val list=ArrayList(此)
list.sortBy(选择器)
清除()
addAll(列表)
}
}
安卓上
inline fun <T, R : Comparable<R>> CopyOnWriteArrayList<T>.sortListBy(crossinline selector: (T) -> R?) {
if (size > 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sortBy(selector)
} else {
val list = ArrayList(this)
list.sortBy(selector)
clear()
addAll(list)
}
}
}
inline fun CopyOnWriteArrayList.sortListBy(交叉内联选择器:(T)->R?){
如果(大小>1){
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.N){
sortBy(选择器)
}否则{
val list=ArrayList(此)
list.sortBy(选择器)
清除()
addAll(列表)
}
}
}
我怀疑堆栈跟踪比这长-显示失败的操作…我建议将其复制到ArrayList,排序并复制回。是的,堆栈跟踪更长。让我编辑并放置完整跟踪。@talex-这将导致相当昂贵的操作。这需要minSDK 24
inline fun <T, R : Comparable<R>> CopyOnWriteArrayList<T>.sortListBy(crossinline selector: (T) -> R?) {
if (size > 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sortBy(selector)
} else {
val list = ArrayList(this)
list.sortBy(selector)
clear()
addAll(list)
}
}
}