【面试】shuffle函数的实现
一、前言
有位同学面试的时候被问到shuffle函数的实现,他之后问我,我知道这个函数怎么用,知道是对数组(或集合)中的元素按随机顺序重新排列。但是没有深入研究这个是怎么实现的。现在直接进入JDK源码进行分析。
二、源码分析
shuffle函数的源码如下
public static void shuffle(List<?> list, Random rnd) {
// 集合大小
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) { // 小于shuffle阈值或者可以随机访问(如ArrayList,访问效率很高)
// 从后往前遍历
for (int i=size; i>1; i--)
// 交换指定位置的两个元素
swap(list, i-1, rnd.nextInt(i));
} else { // 如果大于阈值并且不支持随机访问,那么需要先转化为数组,再进行处理
Object arr[] = list.toArray(); // 该数组只是中间存储过程
// 从后往前遍历
for (int i=size; i>1; i--)
// 交换指定位置的两个元素
swap(arr, i-1, rnd.nextInt(i));
// 重新设置list的值
ListIterator it = list.listIterator();
// 遍历List
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
说明:从源码可知,进行shuffle时候,是分成两种情况。
1. 若集合元素个数小于shuffle阈值或者集合支持随机访问,那么从后往前遍历集合,交换元素。
2. 否则,先将集合转化为数组(提高访问效率),再进行遍历,交换元素(在数组中进行),最后设置集合元素。
其中涉及的swap函数如下,两个重载函数
public static void swap(List<?> list, int i, int j) {
// 交换指定位置的两个元素
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
private static void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
说明:两个重载函数很简单,不再累赘。
三、总结
多看源码,源码也是最直观的。平时多注意积累,水滴石穿。谢谢各位园友的观看~
【面试】shuffle函数的实现的更多相关文章
- shuffle() 函数(转)
定义和用法 shuffle() 函数把数组中的元素按随机顺序重新排列. 若成功,则返回 TRUE,否则返回 FALSE. 注释:本函数为数组中的单元赋予新的键名.这将删除原有的键名而不仅是重新排序. ...
- SSE 系列内置函数中的 shuffle 函数
SSE 系列内置函数中的 shuffle 函数 邮箱: quarrying@qq.com 博客: http://www.cnblogs.com/quarryman/ 发布时间: 2017年04月18日 ...
- 【实践】用 js 封装java shuffle函数(打乱数组下标方法)
此方法返回的会是一个全新的数组 所以并不会像java里的shuffle函数一样返回一个引用一样的数组 思路如下: 1.新建一个函数传入需要打乱下标的数组 2.获取数组的长度 3.新建一个用来保存并且返 ...
- python3中shuffle函数
1. shuffle函数与其他函数不一样的地方 shuffle函数没有返回值!shuffle函数没有返回值!shuffle函数没有返回值!仅仅是实现了对list元素进行随机排序的一种功能 请看下面的坑 ...
- php shuffle()函数 语法
php shuffle()函数 语法 作用:把数组中的元素按随机顺序重新排序:富瑞华 语法:shuffle(array) 参数: 参数 描述 array 必需.规定要使用的数组. 说明:若成功则返回 ...
- SSE系列内置函数中的shuffle函数
SSE 系列内置函数中的 shuffle 函数 邮箱: quarrying@qq.com 博客: http://www.cnblogs.com/quarryman/ 发布时间: 2017年04月18日 ...
- PHP shuffle() 函数
实例 把数组中的元素按随机顺序重新排列: <?php$my_array = array("red","green","blue",&q ...
- 文本数据挖掘---课后作业shuffle函数洗牌C++
题目: 代码如下:#include <iostream> #include <random> #include <algorithm> #include <v ...
- shuffle() 函数
shuffle() 方法将序列的所有元素随机排序. 以下是 shuffle()方法的语法: shuffle (lst ) 注意:此函数是无法直接访问,需要导入 random 模块,然后通过 rando ...
随机推荐
- Python的字节编译
1.什么是Python的.pyc文件 在python中 .pyc文件是指以.pyc为后缀名的这一类文件,在我们的python的安装目录里,找到模块所在的目录Lib会看到很多以.py结尾的模块文件,与之 ...
- 【实战Java高并发程序设计 2】无锁的对象引用:AtomicReference
AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,而AtomicReference则对应普通的对象引用.也就是它可以保证你在修 ...
- 测试MailUtils,作用是发邮件
package cn.itcast.test; import java.io.IOException; import javax.mail.MessagingException; import jav ...
- MongoDB 聚合管道(Aggregation Pipeline)
管道概念 POSIX多线程的使用方式中, 有一种很重要的方式-----流水线(亦称为"管道")方式,"数据元素"流串行地被一组线程按顺序执行.它的使用架构可参考 ...
- 日志系统实战(二)-AOP动态获取运行时数据
介绍 这篇距上一篇已经拖3个月之久了,批评自己下. 通过上篇介绍了解如何利用mono反射代码,可以拿出编译好的静态数据.例如方法参数信息之类的. 但实际情况是往往需要的是运行时的数据,就是用户输入等外 ...
- [Unity3D]自己动手重制坦克舰队ArmadaTank
[Unity3D]自己动手重制坦克舰队ArmadaTank 我玩过一款坦克游戏ArmadaTank(坦克舰队),如下图所示 几个月前我尝试用Unity3D重制这款游戏,已经可以玩起来了.下面是在PC上 ...
- 30个你必须记住的CSS选择符
所以你学会了基础的id,类和后代选择符,然后你就一直用它们了吗?如果是这样,你丢失了(css的)巨大的灵活性.在本文中提到的很多选择器属于CSS3规范的一部分,因此,只有在现代浏览器中才可使用. 1. ...
- Eos开发——ajax请求
function saveData(){ form.validate(); if(form.isValid()==false) return; var persons = grid.getChange ...
- Echarts使用
Echarts使用 |版权声明:此文为本人原创,望尊重原创 前言: 和朋友聊天的过程中,朋友提到了Echarts.我当时不知道那个是用来做什么的.回到家我就百度了,开始自己看文档学习.本文是自 ...
- android studio和eclipse中如何获取sha1值
首先如果是eclipse的话, 直接打开eclipse开发工具 那么接下来问题来了,现在很多开发者都已经从es转型到as开发工具了, 在android studio上没有直接提供这个GUI界面让我们去 ...