要从一个列表中随机去指定数量的数据:
List  aList=new ArrayList();
//假设aList.size()=100,从aList中随机取20条不同的记录
//同时取多遍取出的20条记录也不近相同//例如随机从100道考题中随机取出20道考题,并且每个考生取出的这20道考题不能完全重复。各位帮忙啊,急啊

解决方案 »

  1.   

    public class RandNum {
        
        public int getNum(int maxNum) {
            return (int)(Math.random()*maxNum);
        }
        
        public int [] getAll(int size) {
            int [] result = new int[size];
            int tmp = 0; 
            for (int i = 0; i < size; i++) {
                tmp = getNum(100);
                if (repeat(result,tmp)) {
                    i--;
                    continue;
                }
                result[i] = tmp;
            }
        }
        private boolean repeat(int [] nums,int num) {
            for (int i = 0; i < nums.length; i++) {
                if (num == nums[i]) {
                    return true;
                }
            }
            return false;
        }
    }
      

  2.   

    忘了returnpublic int [] getAll(int size) {
            int [] result = new int[size];
            int tmp = 0; 
            for (int i = 0; i < size; i++) {
                tmp = getNum(100);
                if (repeat(result,tmp)) {
                    i--;
                    continue;
                }
                result[i] = tmp;
            }
            return result;
        }
      

  3.   

    有多少个考生,知道吗?
    如果考生数量不多的话,先写一个从100中随机取20个数,并将结果放入一个 Set 的函数。
    构造一个ArrayList storage。storage储存已经取过的随机数组合。每次调用这个函数后,先比较这个组合是否在storage中已经出现过,如果没有,就插入里面。否则再调用函数,生成新的组合。
    如果考生数目不多的话,这个方法效率不错,而且够简单。如果考生数目达到n=100!/(20!*80!)的一半或者更多的话,那么这个方法就不行了。
    这种情况下,比较好的方法是用一个LinkList availList存储还没有生成的随机数,(应该用BigDecimal,因为long也不够长。)
       首先初始化availList,依次填入1到n。
       然后随机生成一个1到 availList.length()的随机数t。并从availList中移出第t个数,这就是要取的数。重复此操作,直到取出的数满足要求,或者取完availList
      

  4.   

    也可以考虑把序号存入一个LinkedList中
    int size=list.size();
    int[]result = new int[size];
    for(int i=0; i<考题数; i++){
     Integer v = list.remove(Math.random()*(size-i));
     result[i] = (Integer)v.intValue();
    }
      

  5.   

    补充一下,刚才没有说完
    取出的t是一个1到n的数,代表的是一种 20个数的组合。取出来以后,还要把t转换成20个数的组合。这种映射方法很多,自己随便写一个
      

  6.   

    谢谢大家,基本解决了!
    不过 pauliuyou(paul) () 信誉:100 给出的函数取值getAll(100)就不行了,就是说从100个里面取100个随机数就出现错误了!怎么样简单的解决呢?
      

  7.   

    believefym(暮色,miss,迷失,miss) 的方法不错。
    我以前做过是用的Vector v。
    1. v中按顺序放入1-100。
    2. 取出1-v.length中一个随机数r。
    3. 返回v中的第r个元素。
    4. 在v中除去第r个元素。
    5. 重复第2步。由于v中已取的值去掉了,所以可以保证不重复。 //get an int array contains 0-99 in random order 
    public void randomizeNumbers()
    {
    Vector v=new Vector(100);
    Random r=new Random();
    //initialize vector contains 0-99 by order
    for(int i=0;i<100;i++)
    {
    v.addElement(""+i);
    }
    for(int i=99;i>-1;i--)
    {
    //get a pseudo-random number n from 0 to vector's length
    int n=r.nextInt(i+1);
    //ss keeps the number(in String form) in vector's element listed n
    String ss=(String)v.get(n);
    //ss passes the number to s[i](in String form)
    s[i]=ss;
    //remove element listed n
    v.remove(n);
    }
    }
      

  8.   

    用random()的话,你所取的范围必须比你要取的数的个数大的多,这样才能最好的降低重复率,因为用random(),它的取值范围是0<=x<1,那么本身函数的话重复率是很低的,但是你要取的是整数,因此要乘以100,所以重复率就大了。
      

  9.   

    不过 pauliuyou(paul) () 信誉:100 给出的函数取值getAll(100)就不行了,就是说从100个里面取100个随机数就出现错误了!怎么样简单的解决呢?
      

  10.   

    根据pauliuyou(paul) () 信誉:100 的实例改成如下格式:
    在执行getAll(100,100)时会执行不下去,执行getAll(100,<100的值)时就没有问题,请大家看看这是那里出错了呢?
     public static int getNum(int maxNum) {
            return (int)(Math.random()*(maxNum));
        }    public static int [] getAll(int size,int maxNum) {
            int [] result = new int[size];
            int tmp = 0;
            for (int i = 0; i < size; i++) {
                tmp = getNum(maxNum);
                if (repeat(result,tmp)) {
                    i--;
                    continue;
                }
                result[i] = tmp;
            }
            return result;
        }
        private static boolean repeat(int [] nums,int num) {
            for (int i = 0; i < nums.length; i++) {
                if (num == nums[i]) {
                    return true;
                }
            }
            return false;
        }
      

  11.   

    to pcno1(风火):用random(),它所取的数是一个double类型的,由于精确度很高,所以它所取到的数的重复率几乎为0。但是楼主是要从1-100这100个数中取,那么就要对产生的随即数进行处理,也就是要乘以100,这样才能确保取出的书在1-100之间。假如用random()随即产生的两个数是0.5552 另一个是.05553  那么它们乘以100后,所得到的int值应该都是56,这样的话就重复了。假如是按照 pcno1(风火)的方法,进行判断的话,我觉得这样就破坏了随即取数的原则了。
      

  12.   

    这个问题好像讨论过了。random*100,取整,再随机,这类方法的取数重复率很高。至于有人说用不断删除的方式,看上去可行,不过总是有些别扭。
      

  13.   

    to wangzhisheshou(王之射手) :
    你的这个方法已经被我注册了,呵呵。
      

  14.   

    wangzhisheshou(王之射手)的方法好,效率高,且不重复
    如果你想让相邻的考生考题不重复的话,可以在第一个考生抽题之后在剩下的考题中为第二个考生抽题,这样依次类推就可以做到了。
      

  15.   

    给你一段C++代码:
    int a[100];
    for(int i = 0; i < 100; i++)
    {
    a[i] = i;
    }for(int i = 0; i < 50; i++)
    swap(a[rand() * 100 / RAND_MAX], a[rand() * 100 / RAND_MAX]);for(int i = 0; i < 20; i++)
    cout << a[i] << endl;