Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何对CopyOnWriteArrayList进行排序_Java_Core_Copyonwritearraylist - Fatal编程技术网

Java 如何对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

我想对CopyOnWriteArrayList进行排序。但是当我尝试运行以下代码时

它正在引发
未排序的操作异常

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)
        }
    }
}