在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之集合乱序源码分析的更多相关文章

  1. 死磕 java集合之ConcurrentHashMap源码分析(三)

    本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...

  2. 死磕 java集合之DelayQueue源码分析

    问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...

  3. 死磕 java集合之PriorityBlockingQueue源码分析

    问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...

  4. 死磕 java集合之PriorityQueue源码分析

    问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...

  5. 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计

    问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...

  6. 死磕 java集合之LinkedHashSet源码分析

    问题 (1)LinkedHashSet的底层使用什么存储元素? (2)LinkedHashSet与HashSet有什么不同? (3)LinkedHashSet是有序的吗? (4)LinkedHashS ...

  7. 死磕 java集合之ArrayDeque源码分析

    问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...

  8. 死磕 java集合之LinkedList源码分析

    问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...

  9. 【死磕 Java 集合】— ConcurrentSkipListMap源码分析

    转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...

随机推荐

  1. vue.js 源代码学习笔记 ----- 工具方法 perf

    import { inBrowser } from './env' export let mark export let measure if (process.env.NODE_ENV !== 'p ...

  2. root用户下使用sqlplus登录Oracle数据库

    1.把环境变量添加到root用户的环境变量里面2.执行 chmod -R 6777 /tmp           chmod -R 6777 /usr/tmp           chmod -R 6 ...

  3. 我也说说Emacs吧(3) - 文件基本操作

    Spacemacs文件基本操作 有了前两讲的积累,我们知道了: 1. 我们既要学习emacs的操作,也要学习vi的操作 2. emacs是一个可扩展的平台,我们并不是从头配置,而是使用一套成熟的集成方 ...

  4. java入门学习(3)—循环,选择,基础算法,API概念

    1.顺序结构:也就是顺着程序的前后关系,依次执行.2.选择分支:利用if..else , / switch(){case [ 这个必须是常量]:}; / if..else if….. ….else.. ...

  5. C# Thrift 实战开发 从PLC到Thrift再到客户端集成开发

    About Thrift: 本文并不是说明Thrift设计及原理的,直接拿Thrift来开发一个Demo程序,如果想要了解Thrift的细节,可以访问官方网站:https://thrift.apach ...

  6. Java面试题收集以及参考答案(100道)

    不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...

  7. 网络编程 socket编程 - Asyncsocke

    简单的聊天程序:http://blog.csdn.net/chang6520/article/details/7967662 iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 c ...

  8. 类中的__slots__方法与__dict__方法相排斥

    类的 __slots__ 列表 作用: 限定一个类创建的实例只能有固定的属性(实例变量) 不允许对象添加列表以外的属性(实例变量) 防止用户因错写属性的名称而发生程序错误 说明: 1. __slots ...

  9. C# 速编神器LinqPad(新版5.25)

    点此下载5.25 (支持.net4.6,有调试器)(页面有广告,一直点免费下载即可)(可用)密码  lp123456  批处理如下. @echo off start /b LINQPad.exe -n ...

  10. Jmter-Test Fragment、Include Controller和Module Controller

    Test Fragment--测试片段 The Test Fragment is used in conjunction with the Include Controller and Module ...