【算法】【源码】Collections.shuffle 求给定集合的随机排列
1 问题描述
类似这种,现有数组1、2、3、4、5、6、7、8,编程实现对该数组随机排序的算法题,因为Collections类有一个随机排列集合的方法,所以我们直接看一下人家是怎么写的。
2 源码分析
// 主要的思想就是:从第n个元素开始跟它前边的1到n-1的随机其中一个元素进行交换 // 1、如果是列表的长度小于5或者列表实现是随机访问接口,就直接在列表中调整顺序 // 2、其他情况,把列表转成对象数组,把数组的存储的值的顺序打乱,然后再把数组转成列表。 // 可见源码中考虑代价问题了,列表小的时候直接调整的代价很小,如果列表很大的情况,直接在列表中调整会有效率问题,转成数组,数组查找的效率很高,调换代价就小很多了 private static final int SHUFFLE_THRESHOLD = 5; public static void shuffle(List<?> list, Random rnd) { int size = list.size(); // 长度小于5或者集合是可以随机访问的 就直接进行变换 随机访问这里可以理解为元素都在一块 比如数组 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]); } } } public static void swap(List<?> list, int i, int j) { final List l = list; // 利用集合的特性 巧妙转换 即set方法会返回当前下标的值 l.set(i, l.set(j, l.get(i))); } private static void swap(Object[] arr, int i, int j) { Object tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
多看源码,多学习,大家加油!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了