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

在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. 18 —— node 热部署工具 — supervisor /nodemon 。

    1,全局安装: npm install -g supervisor 2,使用: —————————————————————————————— nodemon 和 supervisor 流程一致.

  2. 【LeetCode】两个数相加

    [问题]给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. [实例] 输入: ...

  3. 算法5:队列——解密 QQ 号

    新学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问 QQ 号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则.规则是这样的 ...

  4. java向python ,text文件动态传参或传值问题完美解决

    由于业务需要对python文件进行参数传递,通过下面两个java方法完美解决此问题,我的思路是:首先我要先把上次写的参数删除,第二我要新的参数写到python文件中. 第一个方法解决了删除上次传递的参 ...

  5. exgcd详解

    注:本文中所有 \(\%\) 号均表示取模, \(gcd(a,b)\) 表示 \(a\) 和 \(b\) 的最大公因数 1.exgcd是什么? exgcd大名扩展欧几里得算法,用来求形如 \(gcd( ...

  6. LIS是什么?【标本分拣】

    接之前[LIS是什么?]中,提到几点需要补充描述的部分. Ⅰ.标本分管处理 标本的分管处理,在医院和第三方实验室有多种叫法,例如:分拣.合管等等.这里我称之为分拣,分拣实际上分为两个部分:系统中标本分 ...

  7. JavaBean和json数据之间的转换(一)简单的JavaBean转换

    1.为什么要使用json? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,因为其高性能.可读性强的原因,成为了现阶段web开发中前后端交互数据的主要数据 ...

  8. 用Python在00:00给微信好友发元旦祝福语

    2019年的元旦即将来临,这里用Python撸一串简单的代码来实现定点给微信里的所有小伙伴发祝福语 环境说明 Python版本: 不限 第三方库: itchat, schedule 注:所有祝福语来源 ...

  9. POJ 1129:Channel Allocation 四色定理+暴力搜索

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13357   Accepted: 68 ...

  10. LINUX文件目录存放文件说明

    /bin bin是Binary的缩写.这个目录存放着最经常使用的命令. /boot这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件. /dev dev是Device(设备) ...