在工作中发现有很多有序算法,较少见到一些可用的无序随机算法。无序随机算法的目的是让客户感觉每次都不一样,因为一直看一样的会审美疲劳哈。

在jdk自带一种CollectionUtils.shuffle<List<?> list> 使用默认随机源对指定列表进行置换,方便快捷。熟读JDK是如此的重要。

一下两种算法适用于一些特殊场合

特意写了两种算法。一种是利用set集合的特性,加上优化,因为如果list的个数不大,要在list中取的个数比较多的情况下,采用逆向生成算法,最佳适用于大数据量选取少量随机元素。

另外一种是随机置换位置法,每一个位置都有一次换位的机会,最佳适用于小数据量选取大量随机元素。

有好的意见可以分享给我哈。

package com.duotin.japi.common.utils;

import com.duotin.util.CollectionUtils;
import org.apache.commons.lang.math.RandomUtils; import java.util.*; /**
* 生成随机集合工具类
*
*/
public class RandomDataUtil {
public final static int TWO=2;
/**
* 生成随机集合(不重复)
* <p>
* 使用Set的值唯一的特性。
* 最佳适用场合:集合中数目多,取相对较少对象时。在取对象相对较多时(超过集合的一半时)采用逆向方法,
* 在取得对象个数是集合总数的1/2左右时是效率最慢的。
* </p>
* @param list
* @param generateNum 生成集合中元素的个数
* @param <T>
* @return
*/
public <T> List<T> generateRandomDataNoRepeat(List<T> list,Integer generateNum){
List<T> tList = new ArrayList<T>();
if(CollectionUtils.isNotEmpty(list)) {
for (Integer num : generateRandomNoRepeat(list.size(), generateNum)) {
tList.add(list.get(num));
}
}
return tList;
} /**
* 生成随机集合,随机置换位置、随机截取位置法。
* <p>
* 随机置换法:将集合的每个位置值与随机位置的值调换,并随机截取位置.
* 最佳适合场合:集合的数量相对较少,获取较多的随机个数集合。
* </p>
* @param list
* @param generateNum
* @param <T>
* @return
*/
public <T> List<T> generateRandomPermutation(List<T> list,Integer generateNum){
if(CollectionUtils.isNotEmpty(list)) {
checkParams(list.size(),generateNum);
List<T> randomAllList = randomPermutation(list, generateNum);
int initPosition=interceptPosition(list.size(),generateNum);
return randomAllList.subList(initPosition,initPosition+generateNum);
}
return Collections.emptyList();
} /**
* 随机置换算法
* @param list
* @param generateNum
* @param <T>
* @return
*/
private <T> List<T> randomPermutation(List<T> list,Integer generateNum){
for (int i = 0; i < list.size(); i++) {
Integer random=RandomUtils.nextInt(list.size());
T t = list.get(random);
list.set(random,list.get(i));
list.set(i,t);
}
return list;
} /**
* 随机生成截取位置
* @param totalCount
* @param generateNum
* @return
*/
private Integer interceptPosition(Integer totalCount,Integer generateNum){
int num=RandomUtils.nextInt(totalCount);
if(num+generateNum>totalCount){
num=num-generateNum;
}
return num;
}
/**
* 生成不重复的随机数
* @param totalCount
* @param generateNum
* @param
* @return
*/
public Set<Integer> generateRandomNoRepeat(Integer totalCount,Integer generateNum){
if(isLessThanHalfTotalCount(totalCount,generateNum)){
return getRandomNoRepeat(totalCount,generateNum);
}
return getReverseRandomNoRepeat(totalCount,generateNum);
} /**
* 验证参数是否合法
* @param totalCount
* @param generateNum
*/
private void checkParams(Integer totalCount,Integer generateNum){
if(totalCount<generateNum){
throw new IllegalArgumentException("generateNum is out of totalCount");
}
} /**
* 判断使用哪种生成机制
* @param totalCount
* @param generateNum
* @return
*/
private Boolean isLessThanHalfTotalCount(Integer totalCount,Integer generateNum){
if(generateNum<totalCount/TWO){
return Boolean.TRUE;
}
return Boolean.FALSE;
} /**
* 生成set,不重复
* @param totalCount
* @param generateNum
* @return
*/
private Set<Integer> getRandomNoRepeat(Integer totalCount,Integer generateNum){
Set<Integer> set = new HashSet<Integer>();
while (true) {
set.add(RandomUtils.nextInt(totalCount));
if(set.size() == generateNum){
return set;
}
}
} /**
* 逆向生成set,不重复
* @param totalCount
* @param generateNum
* @return
*/
private Set<Integer> getReverseRandomNoRepeat(Integer totalCount,Integer generateNum){
Set<Integer> set = new HashSet<Integer>();
while (true) {
set.add(RandomUtils.nextInt(totalCount));
if(set.size() == totalCount-generateNum){
Set<Integer> setALL=getSetALL(totalCount);
setALL.removeAll(set);
return setALL;
}
}
} /**
* 生成Set
* @param totalCount
* @return
*/
private Set<Integer> getSetALL(Integer totalCount){
Set<Integer> set = new HashSet<Integer>();
for(int i=0;i<totalCount;i++){
set.add(i);
}
return set;
} }

从list中取N个随机生成一个集合的更多相关文章

  1. PYTHON练习题 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数。

    Python 练习 标签: Python Python练习题 Python知识点 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数,如果大于预设的 ...

  2. 转:在0~N(不包括N)范围内随机生成一个长度为M(M <= N)且内容不重复的数组

    1. 最朴素暴力的做法. void cal1() { , j = , num = ; int result[M]; result[] = rand() % N; //第一个肯定不重复, 直接加进去 ; ...

  3. JAVA代码:生成一个集合,自定义大小,100以内的随机整数

    JAVA代码:生成一个集合,自定义大小,100以内的随机整数 方法一:(Random类) package com.dawa.test; import java.util.ArrayList; impo ...

  4. (爬虫)随机生成一个header

    #!/usr/bin/env python #-*- coding: utf-8 -*- #__Author__: yunrui #__Version__: 1.0 #__Time__: 2019/1 ...

  5. python接口自动化中,注册接口随机生成手机号码

    如大家所知在注册接口中,手机号参数需要的是未注册的手机号,而在测试用例中,你写入的手机号不一定是未注册的.所以这时需要对注册接口中传入的手机号做处理.下面我就分享一个课程里面学到的一个处理手机号的py ...

  6. js随机生成一个数组中的随机字符串以及更新验证码

    随机生成m,n范围的值得公式: Math.random()*(n-m)+m: 改正公式:Math.random()*(n+1-m)+m // 生成随机字符串function randomMixed(n ...

  7. 随机获取一个集合(List, Set)中的元素,随机获取一个Map中的key或value

    利用Java提供的Random类.从List或Set中随机取出一个元素,从Map中随机获取一个key或value. 因为Set没有提供get(int index)方法,仅仅能先获取一个随机数后.利用一 ...

  8. 随机获取一个集合(List, Set,Map)中的元素<转>

    import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; impo ...

  9. JS中取整以及随机颜色问题

    前言:感觉自己已经好久好久没有写博客了,最近都是在写在线笔记比较多.现在来到新公司了,昨天刚刚完成一个项目所以今天有空研究研究一下前端方面的技术.下午在看一个游戏代码的时候,发现了几个别人留下的不错的 ...

随机推荐

  1. 基于thinkphp的邮件群发系统的设计

    在网上找了很多资料,关于邮件群发系统的开发并没有一个非常好的方案,冥思苦相数日,研究了一套目前使用稍微有点效果的邮件群发系统,特地来分享一下,当然有过有更好的方案,欢迎大家一起讨论,或者私聊一下我. ...

  2. 二十、CI框架数据库操作之查看生产的sql语句

    一.代码如下: 二.我们访问一下: 三.我们对比一下数据库内容 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  3. JS高级学习笔记(9) 之 转:前端路由跳转基本原理

    原文链接: 前端路由跳转基本原理 前述 前端三大框架Angular.React和Vue都推行单页面应用SPA开发模式,这是因为在路由切换时,替换DOM Tree中发生修改的DOM部分,来减少原来因为多 ...

  4. swift中实现cell中局部播放的动画效果

    在cell中 // 播放器动画效果 private var replicatorLayer:ReplicatorLayer = { let layer = ReplicatorLayer.init(f ...

  5. 多线程开发之NSThrea

    创建并启动 先创建线程,再启动 // 创建   NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector( ...

  6. Essay写作没灵感怎么办?

    进入6月了,童鞋们都在干啥呢?有人回国玩耍了,有人周游欧洲了,当然也有人还在悲催地上课写作业.但是呢不管你此刻在哪里,final essay或者dissertation都离你不远啦!可是可是,有些留学 ...

  7. linux下启动mysql提示:Timeout error occurred trying to start MySQL Daemon

    启动 mysqld 时经过很长时间显示 Timeout error occurred trying to start MySQL Daemon. 终端进入 mysql 时显示 ERROR 2002 ( ...

  8. Hibernate(二)——一对多查询

    1. 前言 本章节我们讨论Hibernate一对多查询的处理. 在上一章节中(Hibernate(一)——入门),我们探讨了Hibernate执行最基本的增删改查操作.现在我们将情况复杂化:加入我们在 ...

  9. CTF -攻防世界-web高手区-mfw

    ---恢复内容开始--- 昂,我很菜这是网上大神的教程. https://blog.csdn.net/silence1_/article/details/89741733 ---恢复内容结束---

  10. 吴裕雄--天生自然 JAVASCRIPT开发学习:函数调用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...