Java中高效生成某一区间内的不重复的随机数字(BitMap方法实现)

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、运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值