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
    评论
RandomJava中用于生成随机数的。它提供了多个方法用于生成不同型的随机数。其中一些常用的方法包括: - `public boolean nextBoolean()`:生成一个随机的布尔值,即true或false。 除此之外,Random还提供了其他用于生成随机数的方法,如生成整数、浮点数、字节等。这些方法都是基于种子数(seed)进行一定的变换,从而生成需要的随机数字。种子数可以通过构造Random对象时传入参数进行设置,如果不指定种子数,则默认使用当前时间作为种子数。 使用Random时,可以通过调用不同的方法来生成指定区间的随机数。例如,可以使用`nextInt(int bound)`方法生成一个在指定范围内的随机整数,其中bound参数指定了上限(不包含)。如果需要生成指定范围内的随机浮点数,则可以使用`nextDouble()`方法生成一个0到1之间的随机浮点数,并根据需要进行线性变换。 通过使用Random的方法,我们可以在程序中实现需要的随机性和几率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [JAVARandom常用用法](https://blog.csdn.net/qq_37857292/article/details/124397982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [JAVA Random](https://blog.csdn.net/wztmds/article/details/127586834)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值