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集合排序异常问题的更多相关文章

  1. .NET 基础 一步步 一幕幕[数组、集合、异常捕获]

    数组.集合.异常捕获 数组: 一次性存储多个相同类型的变量. 一维数组: 语法: 数组类型[] 数组名=new 数组类型[数组长度]; 声明数组的语法: A.数据类型 [] 数组名称= new 数据类 ...

  2. Java比较器对数组,集合排序一

    数组排序非常简单,有前辈们的各种排序算法,再加上Java中强大的数组辅助类Arrays与集合辅助类Collections,使得排序变得非常简单,如果说结合比较器Comparator接口和Collato ...

  3. ArrayList集合排序

    using System;using System.Collections;using System.Collections.Generic;using System.Text; namespace ...

  4. 【Java进阶】---map集合排序

    map集合排序         这篇文章讲的不仅仅是map排序,比如把对象按某一属性排序,它都可以解决这些问题.   比如,有N个对象,每个对象有个属性就是成绩,成绩分:优秀,良好,合格.那我们如何按 ...

  5. 二维码扫描&集合排序

    一.二维码扫描机制 二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的:在代码编制上巧妙地利用构 ...

  6. .Net中集合排序的一种高级玩法

    背景: 学生有名称.学号, 班级有班级名称.班级序号 学校有学校名称.学校编号(序号) 需求 现在需要对学生进行排序 第一排序逻辑 按学校编号(序号)排列 再按班级序号排列 再按学生学号排列 当然,在 ...

  7. Java集合排序及java集合类详解--(Collection, List, Set, Map)

    1         集合框架 1.1         集合框架概述 1.1.1         容器简介 到目前为止,我们已经学习了如何创建多个不同的对象,定义了这些对象以后,我们就可以利用它们来做一 ...

  8. Java提高(5)---map集合排序

    map集合排序 这篇文章讲的不仅仅是map排序,比如把对象按某一属性排序,它都可以解决这些问题. 比如,有N个对象,每个对象有个属性就是成绩,成绩分:优秀,良好,合格.那我们如何按照成绩的好坏进行排序 ...

  9. 集合排序 Comparator和Comparable的使用区别

    Java 排序 Compare  Comparator接口 Comparable接口 区别 在Java中使用集合来存储数据时非常常见的,集合排序功能也是常用功能之一.下面看一下如何进行集合排序,常用的 ...

随机推荐

  1. for循环找出2到100的质数(素数)

    思路: 1,一个数只有1和它本身两个因数,这个数叫质数. 2.注意:缩进这里else是for循环这个上下文的. 代码: for num in range(2,100): #为大循环变量num提供2-1 ...

  2. 【读书笔记】【深入理解ES6】#4-扩展对象的功能性

    对象类别 ES6规范清晰定义了每一个类别的对象. 普通(Ordinary)对象 具有JS对象所有的默认内部行为 特异(Exotic)对象 具有某些与默认行为不符的内部行为 标准(Standard)对象 ...

  3. Android之Bmob移动后端云服务器

    源码下载:http://download.csdn.net/download/jjhahage/10034519 PS:一般情况下,我们在写android程序的时候,想要实现登录注册功能,可以选择自己 ...

  4. GO开发[三]:fmt,strings,strconv,指针,控制结构

    一.fmt包 %v 值的默认格式表示.当输出结构体时,扩展标志(%+v)会添加字段名 %#v 值的Go语法表示 %T 值的类型的Go语法表示 %% 百分号 %t 单词true或false %b 表示为 ...

  5. EMMC与nand flash的区别【转】

    1.NAND Flash 是一种存储介质,要在上面读写数据,外部要加主控和电路设计. 2.eMMC是NAND flash+主控IC ,对外的接口协议与SD.TF卡类似:对厂家而言简化了电路设计,降低了 ...

  6. CSS基础知识(概念、块级元素、行内元素、选择器)

    1.CSS概念 全称为Cascading Style Sheets(层叠样式表),支持专有的文件 - 扩展名为".css" 作用:将HTML的结构(HTML标签即html)与样式( ...

  7. java调用c++函数的简单笔记

    java使用jni调用c++动态库函数. 步骤: 1.编写java测试代码如下: public class CallNativeDemo { native void func(); native do ...

  8. JS 引擎的执行机制

    关于JS引擎的执行机制,首先牢记2点: .JS是单线程语言 JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 关于单线程相对还比较好理解,就是 ...

  9. python写外网收集信息器

    简单化,知道IP去扫描ip import socket from socket import * a=input('请输入域名:') try: ip=gethostbyname(a) print('[ ...

  10. keepalived VS zookeeper

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/e3db73cb83afb213a3bff43a850d56c4.html keepalived VS zook ...