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. python 豆瓣采集

    新手今天刚学python~~~ 有点凌乱~勉强看吧 只能算是给新手看看,见谅 简单版本的 豆瓣采集美图~~~~~~ 美女天天有 有木有~~~ python 3.4 sqlite3 BeautifulS ...

  2. windows 线程

    在windows中进程只是一个容器,用于装载系统资源,它并不执行代码,它是系统资源分配的最小单元,而在进程中执行代码的是线程,线程是轻量级的进程,是代码执行的最小单位. 从系统的内核角度看,进程是一个 ...

  3. JavaScript(五)语句

    js 的语句有 表达式语句,  复合语句{}, 空语句, 声明语句 if 默认不写大括号 可以执行 紧接着的一行 do-while do{}while() while for(初始化:判断:更新){执 ...

  4. css3 移动端 开关效果

    展示效果: 首先是html <div class="container"> <div class="bg_con"> <input ...

  5. ajax--->简单加法小练习

    ajax--->简单加法小练习 index.HTML <!DOCTYPE html> <html lang="en"> <head> &l ...

  6. html笔记4

    <html> <body> <p>这是列表标签</p> <ul> <li>xxx</li> </ul> ...

  7. meterpreter_paranoid_mode.sh允许用户安全上演/无级连接Meterpreter经检查合格证书的处理程序正在连接到

    刚刚看完即刻安全大咖的新姿势感觉很6逼,结果成功了meterpreter_paranoid_mode.sh允许用户安全上演/无级连接Meterpreter经检查合格证书的处理程序正在连接到. 我们开始 ...

  8. CSS3让长单词与URL地址自动换行——word-wrap属性

    div{ word-wrap:break-word; } word-wrap属性可以使用的属性值为normal与break-word两个.使用normal属性值时浏览器默认处理,只在半角空格或者连字符 ...

  9. DOCKER 开发学习记录

    DOCKER常用命令及参数 DOCKER镜像管理命令: 检索:docker search image_name 下载:docker pull image_namge 查看本地镜像:docker ima ...

  10. NYOJ 题目77 开灯问题(简单模拟)

    开灯问题 时间限制:3000 ms  |            内存限制:65535 KB 难度:1           描述 有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 ...