CopyOnWriteArrayList集合排序异常问题
1、集合自定义排序实现
对List集合的自定义排序想必大家都知道要使用如下的方式,通过实现Comparator接口并实现compare方法来实现。
/**
*
* @方法名 changeChain
* @描述 改变请求链
* @参数
* @返回类型 void
* @作者 cymiao
*/
public static void changeChain(Class<? extends Chain> type){
List<? extends Chain> list = DynamicLoader.getInstance().getChainList(type);
Collections.sort(list, new Comparator<Chain>(){ @Override
public int compare(Chain chain1, Chain chain2) {
int orderO = ((OrderAnnotation)chain1.getClass().getAnnotation(OrderAnnotation.class)).value();
int orderT = ((OrderAnnotation)chain2.getClass().getAnnotation(OrderAnnotation.class)).value();
if(orderO > orderT){
return 1;
}else if(orderO < orderT){
return -1;
}
return 0;
} });
List<Chain> aList = new CopyOnWriteArrayList<Chain>();
aList.addAll(list);
DynamicLoader.getInstance().setChainList(aList, type);
}
2、CopyOnWriteArrayList集合排序异常问题
在不同版本的JDK时,CopyOnWriteArrayList集合使用如上方法排序的时候会抛出UnsupportedOperationException异常,这是为什么呢?下来让我们通过研究CopyOnWriteArrayList类的源码来说明这个问题:
(1)、我们先来分析下JDK1.6中Collections.sort的实现逻辑
如下JDK1.6的源码所示,在自定义排序时,先使用Arrays.sort对集合的Object数组进行排序,然后通过调用集合的listIterator()方法获取ListIterator对象,并调用对象的set(E e)方法赋值,我们再看CopyOnWriteArrayList集合的源码,发现listIterator()方法返回的是new COWIterator<E>(getArray(), 0);对象,而这个对象的set方法没有具体实现而是直接抛UnsupportedOperationException异常,所以问题很显而易见了,在JDK1.6版本下是不能对CopyOnWriteArrayList集合使用Comparator来进行自定义排序的。
public static <T> void sort(List<T> paramList, Comparator<? super T> paramComparator)
{
Object[] arrayOfObject = paramList.toArray();
Arrays.sort(arrayOfObject, paramComparator);
ListIterator localListIterator = paramList.listIterator();
for (int i = ; i < arrayOfObject.length; i++) {
localListIterator.next();
localListIterator.set(arrayOfObject[i]);
}
}
/**
* {@inheritDoc}
*
* <p>The returned iterator provides a snapshot of the state of the list
* when the iterator was constructed. No synchronization is needed while
* traversing the iterator. The iterator does <em>NOT</em> support the
* {@code remove}, {@code set} or {@code add} methods.
*/
public ListIterator<E> listIterator() {
return new COWIterator<E>(getArray(), 0);
} static final class COWIterator<E> implements ListIterator<E> {
/** Snapshot of the array */
private final Object[] snapshot;
/** Index of element to be returned by subsequent call to next. */
private int cursor; private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
} public boolean hasNext() {
return cursor < snapshot.length;
} public boolean hasPrevious() {
return cursor > 0;
} @SuppressWarnings("unchecked")
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
} @SuppressWarnings("unchecked")
public E previous() {
if (! hasPrevious())
throw new NoSuchElementException();
return (E) snapshot[--cursor];
} public int nextIndex() {
return cursor;
} public int previousIndex() {
return cursor-1;
} /**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code remove}
* is not supported by this iterator.
*/
public void remove() {
throw new UnsupportedOperationException();
} /**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code set}
* is not supported by this iterator.
*/
public void set(E e) {
throw new UnsupportedOperationException();
} /**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code add}
* is not supported by this iterator.
*/
public void add(E e) {
throw new UnsupportedOperationException();
}
}
(2)、接下来我们分析下JDK1.8中Collections.sort的实现逻辑
如下Collections类的源码所示,1.8版本中修改了集合排序的逻辑,不是直接在Collections类中排序,而是调用集合对象自己的sort方法实现排序了,在JDK1.6中CopyOnWriteArrayList是没有sort方法实现的,在1.8中添加了sort的实现,源码如下,集合的Object数组排序完成以后,直接把排序后的数据赋值给了集合中的Object数据,所以在JDK1.8中能对CopyOnWriteArrayList集合使用Comparator来进行自定义排序的。
/**
* Sorts the specified list according to the order induced by the
* specified comparator. All elements in the list must be <i>mutually
* comparable</i> using the specified comparator (that is,
* {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
* for any elements {@code e1} and {@code e2} in the list).
*
* <p>This sort is guaranteed to be <i>stable</i>: equal elements will
* not be reordered as a result of the sort.
*
* <p>The specified list must be modifiable, but need not be resizable.
*
* @implNote
* This implementation defers to the {@link List#sort(Comparator)}
* method using the specified list and comparator.
*
* @param <T> the class of the objects in the list
* @param list the list to be sorted.
* @param c the comparator to determine the order of the list. A
* {@code null} value indicates that the elements' <i>natural
* ordering</i> should be used.
* @throws ClassCastException if the list contains elements that are not
* <i>mutually comparable</i> using the specified comparator.
* @throws UnsupportedOperationException if the specified list's
* list-iterator does not support the {@code set} operation.
* @throws IllegalArgumentException (optional) if the comparator is
* found to violate the {@link Comparator} contract
* @see List#sort(Comparator)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
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();
}
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
CopyOnWriteArrayList集合排序异常问题的更多相关文章
- .NET 基础 一步步 一幕幕[数组、集合、异常捕获]
数组.集合.异常捕获 数组: 一次性存储多个相同类型的变量. 一维数组: 语法: 数组类型[] 数组名=new 数组类型[数组长度]; 声明数组的语法: A.数据类型 [] 数组名称= new 数据类 ...
- Java比较器对数组,集合排序一
数组排序非常简单,有前辈们的各种排序算法,再加上Java中强大的数组辅助类Arrays与集合辅助类Collections,使得排序变得非常简单,如果说结合比较器Comparator接口和Collato ...
- ArrayList集合排序
using System;using System.Collections;using System.Collections.Generic;using System.Text; namespace ...
- 【Java进阶】---map集合排序
map集合排序 这篇文章讲的不仅仅是map排序,比如把对象按某一属性排序,它都可以解决这些问题. 比如,有N个对象,每个对象有个属性就是成绩,成绩分:优秀,良好,合格.那我们如何按 ...
- 二维码扫描&集合排序
一.二维码扫描机制 二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的:在代码编制上巧妙地利用构 ...
- .Net中集合排序的一种高级玩法
背景: 学生有名称.学号, 班级有班级名称.班级序号 学校有学校名称.学校编号(序号) 需求 现在需要对学生进行排序 第一排序逻辑 按学校编号(序号)排列 再按班级序号排列 再按学生学号排列 当然,在 ...
- Java集合排序及java集合类详解--(Collection, List, Set, Map)
1 集合框架 1.1 集合框架概述 1.1.1 容器简介 到目前为止,我们已经学习了如何创建多个不同的对象,定义了这些对象以后,我们就可以利用它们来做一 ...
- Java提高(5)---map集合排序
map集合排序 这篇文章讲的不仅仅是map排序,比如把对象按某一属性排序,它都可以解决这些问题. 比如,有N个对象,每个对象有个属性就是成绩,成绩分:优秀,良好,合格.那我们如何按照成绩的好坏进行排序 ...
- 集合排序 Comparator和Comparable的使用区别
Java 排序 Compare Comparator接口 Comparable接口 区别 在Java中使用集合来存储数据时非常常见的,集合排序功能也是常用功能之一.下面看一下如何进行集合排序,常用的 ...
随机推荐
- spring boot系列03--spring security (基于数据库)登录和权限控制(下)
(接上篇) 后台 先说一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig 1 @Configuration 2 @EnableWebSecuri ...
- Java实现网页抓取的一个Demo
这个小案例的话我是存放在我的github 上. 下面给出链接自己可以去看下,也可以直接下载源码.有具体的说明 <Java网页抓取>
- 浅谈Android的广告欢迎界面(倒计时)
前些时候就是别人问我他的android APP怎么做一个广告的欢迎界面,就是过几秒后自动跳转到主界面的实现. 也就是下面这种类似的效果.要插什么广告的话你就换张图吧. 那么我就思考了下,就用了andr ...
- centos 6 网卡名称修改
centos6 中网卡的名字有时不是eth0,这时就会带来诸多不便,为此需要修改网卡的名称. 修改网卡名称vim /etc/sysconfig/network-scripts/ifcfg-eno167 ...
- Zabbix实战-简易教程--动作(Actions)--触发器
一.概述 我们通过接入agent,采集了大量数据,但是如果采集到的某个指标超出了我预计的范围(阈值),此时我们希望监控系统能够给予邮件或短信报警,触发器就是替你干这个活的. 触发器表达式允许定义一个什 ...
- 工具:从一个文件夹中复制jar到另一个文件夹中
工具类:从一个文件夹中复制jar到另一个文件夹中 需要的小伙伴可以试一试,很爽哦,有时候真的很需要! 需求:当我们拿到一个maven项目时,而maven项目的jar包都是通过pom.xml文件管理的, ...
- [bzoj3124] [Sdoi2013]直径
看了child学长的题解才知道怎么写TAT http://www.cnblogs.com/ctlchild/p/5160272.html 以前不知道直径都是过重心的..代码改着改着就和标程完全一样了Q ...
- Codeforces Round #331 (Div. 2) _A. Wilbur and Swimming Pool
A. Wilbur and Swimming Pool time limit per test 1 second memory limit per test 256 megabytes input s ...
- HDU--2021
发工资咯:) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- Myeclipse2014 已有项目更换JDK
原先项目使用JDK是1.7,今天项目加入了一个新包,只支持JAVA8,让我们都升级一下本地的JDK,我突然发现我还没有在myeclipse上升级过JDK呢.捣鼓了一下,也不难,记录一下. 1.下载ja ...