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

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

 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;
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值