1、如何高效标记已经使用过的随机数字
要想实现生成不重复的随机数字,方法有好多种,首先需要解决的问题就是如何高效的标记、记录、遍历已经使用过的随机数字,以此来生成一个区间内未使用过的数字,常见的方式是用常用的数据结构HashSet标记去重,内部封装好的数据结构使得遍历效率也比较高,这是常规方法,今天我想通过BitMap,用1比特位来标记一个数字,作利用海量数据处理的方式来实现数据的标记和检索。BitMap的用途很多,用来生成不重复随机数,具体实现如下:
import java.util.ArrayList;
import java.util.Arrays;
public class BitMap {
private byte[] arr;
final private int capacity;
public BitMap(int capacity) {
this.capacity = capacity;
arr = new byte[(capacity / 8 + 1)];
}
public void add(int n) {
//用>>的操作是,运算会比较快
int index = n >> 3;
int position = n & 0x07;
//把1右移和做or操作两步一起
//即 << 对应上图的右移,实际上<<是左移符。
arr[index] |= 1 << position;
}
public void clear() {
byte bit = 0;
Arrays.fill(arr, bit);
}
public int getCapacity() {
return capacity;
}
public void setBitMap(byte[] arr) {
if (arr.length < capacity) {
for (int i = 0; i < arr.length; i++) {
this.arr[i] = arr[i];
}
} else {
this.arr = arr;
}
}
public byte[] getBitMap() {
return arr;
}
public void delete(int n) {
int index = n >> 3;
int position = n & 0x07;
arr[index] &= ~(1 << position);
}
public long getCounter() {
return counter;
}
//失效次数
private long counter = 0;
public boolean counterContain(int n) {
if ((arr[n >> 3] & (1 << (n & 0x07))) != 0) {
counter = 0;
return true;
} else {
++counter;
return false;
}
}
public boolean contain(int n) {
return (arr[n >> 3] & (1 << (n & 0x07))) != 0;
}
public void showByte(byte b) {
byte[] array = new byte[8];
for (int i = 7; i >= 0; i--) {
array[i] = (byte) (b & 1);
b = (byte) (b >> 1);
}
for (byte b1 : array) {
System.out.print(b1);
System.out.print(" ");
}
System.out.println();
}
public void display(int row) {
for (int i = 0; i < row; i++) {
ArrayList<Integer> list = new ArrayList<Integer>();
int temp = arr[i];
for (int j = 0; j < 64; j++) {
list.add(temp & 1);
temp >>= 1;
}
System.out.println("a[" + i + "]" + list);
}
}
public void display() {
for (byte b : arr) {
showByte(b);
}
}
public static void main(String[] args) {
int num[] = {1, 8, 2, 30, 3, 6, 18, 61, 20, 79};
BitMap map = new BitMap(81);
for (int i = 0; i < num.length; i++) {
map.add(num[i]);
}
int temp = 61;
if (map.contain(temp)) {
System.out.println("temp: " + temp + " has already exists");
} else {
System.out.println("temp: " + temp + " not exists");
}
map.display();
map.clear();
map.display();
}
}
2、要实现获得各种需求应用场景下的不重复的随机数
只要实现了合理的去重标记,生成随机数就很简单了。具体实现如下:
import java.util.Random;
public class MyRandom {
private static MyRandom Instance;
private Random random;
private MyRandom() {
random = new Random();
}
public static MyRandom Instance() {
if (Instance == null) Instance = new MyRandom();
return Instance;
}
private MyRandom(long t) {
random = new Random(t);
}
public static MyRandom Instance(long t) {
Instance = null;
Instance = new MyRandom(t);
return Instance;
}
//根据min和max随机生成一个范围在[min,max]的随机数,包括min和max
public int random(int min, int max) {
return min + random.nextInt(max - min + 1);
}
public float random(float min, float max) {
return min + random.nextFloat() * (max - min);
}
//产生(0,len)的一个不重复随机数
public int random(BitMap indexMap) {
int index = random(indexMap.getCapacity() - 1);
if (!indexMap.contain(index)) {
indexMap.add(index);
return index;
} else {
return random(indexMap);
}
}
//[0,range]的随机数
public int random(int range) {
return random.nextInt(range + 1);
}
public int random(BitMap indexMap, int min, int max) {
int index = random(min, max);
if (!indexMap.counterContain(index)) {
indexMap.add(index);
return index;
} else {
if (indexMap.getCounter() > (max - min)) return -1;
return random(indexMap, min, max);
}
}
public void dispose() {
if (random != null) {
random = null;
Instance = null;
}
}
public static void main(String[] args) {
BitMap map = new BitMap(10);
for (int i = 0; i < 10; i++) {
System.out.print(" " + MyRandom.Instance().random(map));
}
System.out.println();
map.clear();
for (int i = 0; i < 7; i++) {
System.out.print(" " + MyRandom.Instance().random(map, 2, 8));
}
MyRandom.Instance().dispose();
}
}
3、运行结果


&spm=1001.2101.3001.5002&articleId=106394253&d=1&t=3&u=a580b0c70d7d44e78398d60343081186)
2477

被折叠的 条评论
为什么被折叠?



