JDK之集合乱序源码分析
在JAVA的JDK中Collections类提供了shuffle方法用来对给定的集合参数进行乱序重排,之前面试也被问到过类似的问题,看了一下JDK的源码实现做个记录
1. 方法签名:
Collections.shuffle方法提供了两个重载的形式分别为:
1. public static void shuffle(List<?> list)
2. public static void shuffle(List<?> list, Random rnd)
在实现上,第一个方法中new了Random对象,然后调用第二个方法,所以我们来看第二重载形式的实现。全部代码如下:
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray(); // Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i)); // Dump array back into list
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
代码解释:
SHUFFLE_THRESHOLD 为Collections类中的静态变量,类型为整形,默认为
if判断中,首先判断要乱序的集合大小,如果集合大小<5,或者集合类型实现了RandomAccess接口,则直接调用集合交换方法。
RandomAccess是一个空接口,个人的理解和Serializable接口一样,起到一个标识的作用,在这里标识集合类是否支持随机访问。
如果支持则随机访问,或者元素个数<5,则直接调用集合交换的swap方法来交换元素(毕竟即使集合不支持RandomAccess,5个
之内的元素交换也不会影响什么性能)。
再看一下集合元素交换的方法:
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
就这么两行代码,不过这里有一点没看懂的是:为什么要声明一个final类型的List来接收参数中的List对象?不明白
交换的规则也很简单,变量 i 是循环内获取的集合的size值-1,也就是集合的最后一个元素,将最后一个元素的值
设置为集合中位置 j 的值,j 的值是random.nextInt(i)来随机获取的集合中的某个位置索引。
所以交换规则就是:
循环,每次将数组的最后一个元素和一个随机获取到的元素进行交换。
再来看else分支中:
能进到else分支,说明集合对象没有实现RandomAccess接口,比如LinkedList没有实现RandomAccess,因为
数据结构的特性,如果访问LinkedList中的元素只能遍历,如果元素多,访问的元素还靠后,访问性能很差,所以JDK在这里
将集合首先转为数组,然后调用数组的元素交换方法,交换规则和之前的规则一样。因为数组有下标,支持随机访问,
所以这样乱序会提高性能。
private static void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
数组元素交换方法如上。
JDK之集合乱序源码分析的更多相关文章
- 死磕 java集合之ConcurrentHashMap源码分析(三)
本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 死磕 java集合之PriorityBlockingQueue源码分析
问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...
- 死磕 java集合之PriorityQueue源码分析
问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...
- 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计
问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...
- 死磕 java集合之LinkedHashSet源码分析
问题 (1)LinkedHashSet的底层使用什么存储元素? (2)LinkedHashSet与HashSet有什么不同? (3)LinkedHashSet是有序的吗? (4)LinkedHashS ...
- 死磕 java集合之ArrayDeque源码分析
问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...
- 死磕 java集合之LinkedList源码分析
问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...
- 【死磕 Java 集合】— ConcurrentSkipListMap源码分析
转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...
随机推荐
- python蛋痛的依赖管理
java有maven 来统一管理项目依赖.初学python不久还没发现类似这样的工具.只有暂时用这个方法来手动操作了. 你可以用pip导出你的dependency: $ pip freeze > ...
- _routing字段介绍
一个document通过以下公式被路由到该索引下一个特定的分片: shard_num = hash(_routing) % num_primary_shards _routing的默认值是文档的_id ...
- 2018-2019 2 20165210 《网络对抗技术》Exp5 MSF基础
2018-2019 2 20165210 <网络对抗技术>Exp5 MSF基础 实验内容: 一个主动攻击实践,如ms08_067(成功); 一个针对浏览器的攻击,如ms10_046(成功) ...
- L157
UK Watchdog: Smugglers to Exploit Border if no Brexit DealSmugglers and other organized criminals ar ...
- Python中字符的练习
一.重复的单词:此处认为分隔符为空格:个整数-]): list.append(random.randint(, ))for i in list: d[i]=list.count(i)print d
- 利用 squid 反向代理提高网站性能(转载)
本文在介绍 squid 反向代理的工作原理的基础上,指出反向代理技术在提高网站访问速度,增强网站可用性.安全性方面有很好的用途.作者在具体的实验环境下,利用 DNS 轮询和 Squid 反向代理技术, ...
- asp.net string有多行文字
用如下格式设置
- 【译】从数学公式入手,详细了解 Animation 的 Interpolators
我们在做动画的时候,总是避免不了会使用到 Interpolator(插值器)这个东西,比如 LinearInterpolator 等.这样做的好处是,能够让动画的变化速度符合现实世界中的物理规律,看上 ...
- 学习三部曲:WHAT、HOW、WHY
一个人学习的过程要经历以下三步,才可以说得上"学会"两字: 第一步:WHAT 所谓的"WHAT",就是搞清楚某个东东是什么?有什么用?有什么语法?有什么功能特性 ...
- 【剑指offer】二叉树的镜像,C++实现(先序遍历)
原创博文,转载请注明出处!github地址 博客文章索引地址 1.题目 输入一颗二叉树,将二叉树变换为原二叉树的镜像,如下图所示: 2.思路 二叉树有0个节点 二叉树有1个节点 二叉树有 ...