java的random类的一个坑(集合乱序)

时间:2018-07-20作者:klpeng分类:IT综合浏览:2175评论:0

引言
在最近的开发中,要实现一个把一个集合的数给弄成乱序的,脑子里边的第一个想法就是使用随机数,先新建一个集合,写个死循环,然后获取随机位置下标,然后判断新集合是否包含这个数,不包含就把这个数加入新集合,包含,就继续下次循环,一直到新集合的长度达到和原始数组一样的长度为止,代码如下:

 public List<String> randomList(List<String> words) {
        if (words == null)
            return null;
        List<String> list = new ArrayList<>();
        Random random = new Random();
        while (true) {
            int i = random.nextInt(words.size());
            // LogUtils.d("random:" + i);
            String s = words.get(i);
            if (list.size() == words.size())
                return list;
            if (list.contains(s))
                continue;
            else
                list.add(s);
        }

    }

这段大吗是没啥问题,刚开始也是,运行的很好,但是过了一段时间之后,发现有的手机会出问题:这个死循环不会结束

后来经过调试,发现,有时候随机数会出现某一个数,一直随机不出不来
,后来查阅文档发现,Random的nextInt(int n)方法有可能会出现问题:

该算法稍微有些复杂。它拒绝那些会导致不均匀分布的值(由于 2^31 无法被 n 整除)。某个值被拒绝的概率取决于 n。最坏的情况是 n=2^30+1,拒绝的概率是 1/2,循环终止前的预计迭代次数是 2。

这是倒霉催的遇上被拒绝的值了,所以应该不能一直nextInt(int n)同一个范围的值。

解决方案

使用JDK自带的方法,Collections的shuffle方法,他的实现方式是:

public static void shuffle(List

public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            // instead of using a raw type here, it's possible to capture
            // the wildcard but it will require a call to a supplementary
            // private method
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

可以看出,它每次nextInt()的随机源是不一样的,所以很好的解决了我碰到的那个问题

修改后的方法代码如下:

   public List<String> randomList(List<String> words) {
        if (words == null)
            return null;
        List<String> list = new ArrayList<>();
        list.addAll(words);
        Collections.shuffle(list);
        return list;
    }
打赏
文章版权声明:除非注明,否则均为彭超的博客原创文章,转载或复制请以超链接形式并注明出处。
相关推荐

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

猜你喜欢