Collections.shuffle
1.Collections.shuffler
最近有个需求是生成十万级至百万级的所有随机数,最简单的思路是一个个生成,生成新的时候排重,但是这样时间复杂度是o(n^2),网上看了几个博客的解决方法都不是很理想
因为是要求生成所有随机数,可以换个思路,即生成顺序数,然后打乱即可。最后用到了shuffler方法,效率很高,百万级的数据毫秒就能打乱完, 其实这个算法也可以用于生成范围内一定量的随机数。
先介绍下源码实现吧,其实思路很简单。
jdk:
shuffle
public static void shuffle(List<?> list)使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。
前面描述中使用了不确定的词“大致”,因为随机源只是大致上独立选择位的无偏源。如果它是一个随机选择位的最佳源,那么算法将完全一致的选择置换。
此实现向后遍历列表,从最后一个元素一直到第二个元素,将随机选择的元素重复交换到“当前位置”。元素是从列表的一部分随机选择的,该部分列表从第一个元素一直到当前位置(包括)。
此方法以线性时间运行。如果指定列表没有实现 RandomAccess 接口并且是一个大型列表,则此实现在改组列表前将指定列表转储到数组中,并将改组后的数组转储回列表中。这避免了二次行为,该行为是原地改组一个“有序访问”列表引起的。
参数:
list - 要改组的列表。
抛出:
UnsupportedOperationException - 如果指定列表或其列表迭代器不支持 set 操作。
shuffle
public static void shuffle(List<?> list,
Random rnd)使用指定的随机源对指定列表进行置换。所有置换发生的可能性都是相等的,假定随机源是公平的。
此实现向后遍历列表,从最后一个元素一直到第二个元素,将随机选择的元素重复交换到“当前位置”。元素是从列表的一部分随机选择的,该部分列表从第一个元素一直到当前位置(包括)。
此方法以线性时间运行。如果指定列表没有实现 RandomAccess 接口并且是一个大型列表,则此实现在改组列表前将指定列表转储到一个数组中,并将改组后的数组转储回列表中。这避免了二次行为,该行为是原地改组一个“有序访问”列表引起的。
参数:
list - 要改组的列表。
rnd - 用来改组列表的随机源。
抛出:
UnsupportedOperationException - 如果指定列表或其列表迭代器不支持 set 操作。
重载函数的思路是一样的, 如果没有穿随机类就生成一个调第二个函数。
java.util.Collections
public static void shuffle(List<?> list) {
if (r == null) {
r = new Random();
}
shuffle(list, r);
}
private static Random r;
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
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
核心就是遍历,首先获取集合的元素个数,如果小于5个或者实现了RandomAccess
接口,就循环一遍,随机交换集合中两个相邻的元素的位置,RandomAccess
是一个标记接口,如果实现了这个接口就表示支持快速的随机访问操作,类似于数组。
如果大于等于5
个元素也没有实现RandomAccess
接口,那么就转为数组,之后也是循环,随机交换集合中两个相邻的元素的位置,最后再将数组放回原来的list中。
Collections.shuffle的更多相关文章
- JAVA Collections.shuffle打乱列表
在JAVA中如果想打乱LIST的顺序可以调用Collections.shuffle()或者Collections.shuffle(List<?> list, Random rnd)方法. ...
- Collections.shuffle()源码分析
Java.util.Collections类下有一个静态的shuffle()方法,如下: 1)static void shuffle(List<?> list) 使用默认随机源对列表进行 ...
- 升序 Collections.sort(list) 降序 Collections.reserve(list) 随机 Collections.shuffle(list)
package Day28ketangzuoye; import java.util.ArrayList; import java.util.Collections; import java.util ...
- Collections.shuffle源码阅读
java.util.Collections /** * Randomly permutes the specified list using a default source of * randomn ...
- Collections -集合排序compareTo方法重写,shuffle,addall
package cn.learn.collection.Collections; /* 排序的对象的类,实现comparable借口,重写compareto方法 若要打印必须重写toString方法, ...
- 可变参数和Collections集合工具类的方法_addAll&shuffle
可变参数 可变参数:是JDK1.5之后出现的新特性 使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数 使用格式:定义方法时使用 ~修饰符 返回值类型 方法名(数据类 ...
- Java基础Map接口+Collections工具类
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- Java基础Map接口+Collections
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- java Collection.shuffle()随机打乱一个顺序数组
如何打乱一个顺序的数组,其实集合的帮助类Collection就有现成的方法可用,而且效率还蛮高的,总比自定义随机数等等方法要好很多.其实乱序就这么简单,步骤如下: 1. 将一个顺序排列的数组添加到集合 ...
随机推荐
- 【Win 10 应用开发】透视效果
所谓透视效果,就是在平面坐标空间上模拟出“好像”三维的效果.要是老周没有记错的话,以前在写WP8相关的内容时写过,UWP中的透视方法也保留了以前的Do法,其实这玩意儿是从 Silverlight 沿袭 ...
- 如何处理CSS3属性前缀
今天闲来无聊,重新来说说CSS3前缀的问题.在春节前和@一丝姐姐说起Sass中有关于gradient的mixins.姐姐说: 为什么还要用mixin呢?为什么不使用Autoprefixer?使用Aut ...
- <JavaScript语言精粹>--<读书笔记三>之replace()与正则
今天有人问我repalce(),他那个题目很有意思.我也不会做,于是我就去查,结果发现就是最基础的知识的延伸. 所以啊最基础的知识才是很重要的,千万不能忽略,抓起JS就写代码完全不知到所以然,只知道写 ...
- 父页面操作iframe子页面的安全漏洞及跨域限制问题
一.父子交互的跨域限制 同域情况下,父页面和子页面可以通过iframe.contentDocument或者parent.document来交互(彼此做DOM操作等,如父页面往子页面注入css). 跨域 ...
- 实例讲解react+react-router+redux
前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...
- 浅玩JavaScript的数据类型判断
前言 平常在需要进行类型判断时,随手拿起typeof就像手枪一样只管突突突...也没有仔细的去了解它的具体特性. 所以这里就利用空闲时间,来做一个较为详细的了解. 首先我们来全面看一遍typeof类型 ...
- redis成长之路——(四)
加强redis连接的连接池 虽然StackExchange.Redis针对连接已经做了很多工作,不过在实际应用场景中还是不够的,比如多实例的vip就会导致只能连到其中一个实例上等:本实例中的连接池只能 ...
- Jquery 页面间传值(非QuerryString)
实现原理: 实现方式不是很复杂,父页面A打开一个子页面 A1,并同时写一个带参数的接收数据函数Receive(result),在A1页面进行逻辑操作,然后调用父页面A的Receive(result)函 ...
- Waud.js – 使用HTML5降级处理的Web音频库
Waud.js 是一个Web音频库,有一个HTML5音频降级处理方案. 它允许您利用Web音频API为你的Web应用程序控制音频功能.在不支持Web音频API的非现代浏览器使用HTML5音频降级方案. ...
- SAP CRM BOL编程基础,代码+详细注释
网络上可以找到一些使用BOL查询.维护数据的DEMO,但几乎都是单纯的代码,缺乏说明,难以理解.本文除了代码外,还给出了详细的注释,有助于理解BOL编程中的一些基本概念. 这是一篇翻译的文章,你可能会 ...