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

在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. UVA 11235 RMQ算法

    上次的湘潭赛的C题,用线段树敲了下还是WA,不知道为何,我已经注意了处理相同数据,然后他们当时用的RMQ. 所以学了下RMQ,感觉算法思想是一样的,RMQ用了DP或者是递推,由单个数到2^k往上推,虽 ...

  2. stringutil stringutils

    org.apache.commons.lang.StringUtils类是用于操作Java.lang.String类的,而且此类是null安全的,即如果输入参数String为null,则不会抛出Nul ...

  3. CMD命令实现数字雨

    首先,我们在桌面上先创建一个“.bat”格式的文件,文件名为“数字雨.bat”,创建好了之后右键点击编辑. 在其中输入: @echo off title 数字雨 color 0a setlocal E ...

  4. C语言编程实现SYN-Flood(Dos)攻击

    ## 实验环境为了方便,直接在win10 VS2013Ultimate实现(攻击机),靶机为同一局域网的另外一台主机或外网服务器.   ## 实验依赖基于WinPcap实现,需要安装WinPcap4. ...

  5. 一、VIP课程:互联网工程专题 01-Git基本概念与核心命令掌握

    第一课:Git基本概念与核心命令掌握.docx 课程概要: GIT 体系概述 GIT 核心命令使用 GIT 底层原理 一.GIT体系概述 1.使用方式区别 从本地把文件推送远程服务,SVN只需要com ...

  6. PHP实现简易微信红包算法

    <?php /** * PHP实现简易的微信红包算法 * @version v1.0 * @author quetiezheng */ function getMoney($total, $pe ...

  7. springboot-jar-web

    预览 与springboot-jar的区别是: 1.pom.xml 将 <dependency> <groupId>org.springframework.boot</g ...

  8. axios请求接口的时候带一个参数

    getHomeInfo () { this.axios.get('/api/index.json?city=' + this.city) .then(this.getHomeInfoSucc) } 尽 ...

  9. POJ 1011:Sticks 经典搜索

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 128734   Accepted: 30173 Descrip ...

  10. SpringCloud学习之手把手教你用IDEA搭建入门项目(二)

    本篇博客是承接上一篇<手把手教你用IDEA搭建SpringCloud入门项目(一)>,不清楚的请到我的博客空间查看后再看本篇博客 1)先创建一个Eureka服务注册中心模块,用来作为服务的 ...