import java.util.Arrays;
import java.util.Random;/**
 * 随机数生成器,规则: <br>
 * 1.11位数字,以'AA'开始;<br>
 * 2.数量为90000,范围以内不重复; <br>
 * @author YC
 */
public class RanderNumberCreator { Random random; /** 生成随机数组,存放不重复的随机数 */
public String[] createRandomNumber() {
// 随机数个数
int numAmount = 90000;
// 范围内最小值
int initNum = 100000000;
// 随机数种子
int rootNum = 900000000;
// 循环范围
int loopRange = numAmount + 10000;
// 循环指针.记录本次数目
int index = 0; // 存放最终结果的字符串数组
String[] numResultArrays = new String[numAmount];
// 存放临时整型数据的数组,范围大些.
int[] intNums = new int[loopRange]; int[] repeatNums = new int[numAmount]; for (int i = 0; i < loopRange; i++) {
int currentNum = getRandomNumber(rootNum, initNum);
// 如果没有重复数据,应该只会循环numAmount次就跳出
if (index == numAmount)
break;
else if (Arrays.binarySearch(intNums, currentNum) < 0) {
intNums[i] = currentNum;
numResultArrays[i] = "AA" + currentNum;
index++;
} else {
System.err.println("------------ 产生重复数据!");
repeatNums[i] = currentNum;
}
} return numResultArrays;
} /**
 * 获取范围内的随机数
 * 
 * @param rootNum
 *            范围种子
 * @param initNum
 *            起始值
 */
protected int getRandomNumber(int rootNum, int initNum) {
random = new Random();
return random.nextInt(rootNum) + initNum;
} public static void main(String[] args) {
String[] results = new RanderNumberCreator().createRandomNumber();
System.err.println(" 随机数组存放: " + results.length);
System.err.println(" 最后一个随机数: " + results[results.length - 1]);
// for(int i=0;i<results.length;i++)
// System.err.println(results[i]);
}}
嘛啊,以前没有怎么看random,查了些资料就写了.有什么bug,请大家指正了.

解决方案 »

  1.   

    // 随机数个数
            int numAmount = 90000;
            // 范围内最小值
            int initNum = 100000000;
            // 随机数种子
            int rootNum = 900000000;
            // 循环范围
            int loopRange = numAmount + 10000;
            // 循环指针.记录本次数目
            int index = 0;这些东西好放参数里控制最好
      

  2.   

    感谢以上的反馈,UUID的话,以前用过32位的做数据库表IDkey,但是没试过生成8位9位这样的,提示下;
    其次,这样判定重复有无问题,还有没有什么好办法能高效的判定是否数组内有重复,这是需求的重点.
      

  3.   

    发现的几个问题    protected int getRandomNumber(int rootNum, int initNum) {
            random = new Random();
            return random.nextInt(rootNum) + initNum;
        }这段代码里的random = new Random();不妥,不用再每次都去创建Random吧;改为在RanderNumberCreator类初始化的时候去创建,如下public class RanderNumberCreator {    Random random  = new Random();
      。。
        protected int getRandomNumber(int rootNum, int initNum) {
            //random = new Random();
            return random.nextInt(rootNum) + initNum;
        }在判断重复时,你用的是折半查找那intNums必须是有序的,
    else if (Arrays.binarySearch(intNums, currentNum) < 0) {
                    intNums[i] = currentNum;
                    numResultArrays[i] = "AA" + currentNum;
                    index++;
                } else {
    但是加入intNums是,没有先找好位置,再插入。
    你可以改成Hash表的方式去查找,更有效率。如下        HashSet<Integer> intNums = new HashSet<Integer>();
            int[] repeatNums = new int[numAmount];        for (int i = 0; i < loopRange; i++) {
                int currentNum = getRandomNumber(rootNum, initNum);
                // 如果没有重复数据,应该只会循环numAmount次就跳出
                if (index == numAmount)
                    break;
                else if (!intNums.contains(Integer.valueOf(currentNum))) {
                    intNums.add(Integer.valueOf(currentNum));
                    numResultArrays[i] = "AA" + currentNum;
                    index++;
                } else {
      

  4.   

    为什么不这样比如,第一次我需要10000个随机数
    我把1到10000加到List中,然后Collections.shuffle一下,取得时候都取第一个。同时在某个地方记住这个10000第二次我又要20000个随机数的时候,我把10001到30000加到一个List中,然后同上面步骤
      

  5.   

    呵呵,确实是每次都创建一个random对象有点搞笑,没有注意到细节;
    现在去跑下你给的修正代码,之前考虑用数组是因为感觉效率好过集合,根据你的建议感觉从数据结构上用hash会好些.
      

  6.   

    现在在需求上有一点还没有确认,到底下次是从本次的基础上生成随机编号还是无所谓重新开始,要和客户去谈谈,
    如果是前者,前次的数据是存放在文件还是数据库比较好,我的倾向是写在文件(2010-xx-xx.txt)类似的情况,然后每次生成前先读取再判断,也还请大家给建议.
      

  7.   

     else if (!intNums.contains(Integer.valueOf(currentNum))) {
      intNums.add(Integer.valueOf(currentNum));
      numResultArrays[i] = "AA" + currentNum;
      index++;发现了数组越界异常,修改了代码numResultArrays[index] = "AA" + currentNum;根据blazingfire的提示,下面是修改完成的代码:/**
     * 创建随机号码:
     * 
     * @param numAmount
     *            随机数个数
     * @param initNum
     *            范围内最小值
     * @param rootNum
     *            随机数种子
     * */
    public String[] createRandomNumber2(int numAmount, int initNum, int rootNum) {
    // 循环范围
    int loopRange = numAmount + 10000;
    // 循环指针.记录本次数目
    int index = 0; // 存放最终结果的字符串数组
    String[] numResultArrays = new String[numAmount]; HashSet<Integer> intNums = new HashSet<Integer>(); int[] repeatNums = new int[numAmount]; for (int i = 0; i < loopRange; i++) {
    int currentNum = getRandomNumber(rootNum, initNum);
    // 如果没有重复数据,应该只会循环numAmount次就跳出
    if (index == numAmount)
    break;
    else if (!intNums.contains(Integer.valueOf(currentNum))) {
    intNums.add(Integer.valueOf(currentNum));
    numResultArrays[index] = "71" + currentNum;
    index++;
    } else {
    System.err.println("------------ 产生重复数据位置:" + index + "[当前随机数:]" + currentNum + ",[当前数组元素值]" + numResultArrays[i]);
    repeatNums[i] = currentNum;
    }
    } return numResultArrays;
    } public static void main(String[] args) {
    String[] results = new RanderNumberCreator().createRandomNumber2(83000,100000000,900000000);
    int length = results.length;
    System.err.println(" 随机数组存放: " + length);
    System.err.println(" 最后一个随机数: " + results[results.length - 1]); for (int i = 0; i < length; i++) {
    if (results[i] == null) {
    System.err.println("结果有空值!");
    }
    }
    }
      

  8.   

    其实你这个代码写的有点纠结,那个循环让人有点难受loopRange又不是真正的循环次数,到最后你用了一句
    if (index == numAmount)
      break;
    来结束这个循环,这种代码可读性就不太好了。其实你可以直接返回一个set就可以了,循环判断set是不是够了你要的随机数个数就好,如下代码是重构后的应该对你有用:    public Set<String> createRandomNumber2(int numAmount, int initNum, int rootNum) {
            Set<String> ret = new HashSet<String>();
            while (ret.size() < numAmount) {
                //因为set里的元素不会有重复的,直接加就好了,加够了numAmount就不加了
                ret.add("71" + getRandomNumber(rootNum, initNum));
            }
            return ret;
        }}如果嫌Set遍历慢,可用ArrayList返回,代码一样可以精简如下:    public List<String> createRandomNumber2(int numAmount, int initNum, int rootNum) {
            // 存放最终结果的字符串
            List<String> ret = new ArrayList<String>();        HashSet<Integer> intNums = new HashSet<Integer>();
            while (ret.size() < numAmount) {
                int currentNum = getRandomNumber(rootNum, initNum);
                if (intNums.add(currentNum)) {
                    ret.add("71" + currentNum);
                }
            }        return ret;
        }
      

  9.   

    再来一个用数组的。    /** 生成随机数组,存放不重复的随机数 */
        public String[] createRandomNumber2(int numAmount, int initNum, int rootNum) {
            // 存放最终结果的字符串
            String[] ret = new String[numAmount];        HashSet<Integer> intNums = new HashSet<Integer>();
            int index = 0;
            while (intNums.size() < numAmount) {
                int currentNum = getRandomNumber(rootNum, initNum);
                if (intNums.add(currentNum)) {
                    ret[index++] = "71" + currentNum;
                }
            }        return ret;
        }
    要注意写有表现力的代码。
      

  10.   

    受益匪浅啊 ,,谢谢blazingfir