你会用shuffle打乱列表吗?
在网站上我们经常会看到关键字云(Word Cloud)和标签云(Tag Cloud),用于表明这个关键字或标签是经常被查阅的,而且还可以看到这些标签的动态运动,每次刷新都会有不一样的关键字或便签,让浏览者觉得这个网站的访问量非常大,短短的几分钟就有这么多的搜索量。这是怎么实现的呢?其实非常简单:先从数据库中读出标签,然后使用随机数打乱,每次都产生不同的顺序,嗯,确实能让浏览者感觉到我们的标签云顺序在变——浏览者多嘛!但是,对于乱序处理我们有哪些方法呢?
下面给出一个大家都会想到的方法:
public <T> void shuffle1(List<T> list) { int size = list.size(); Random random = new Random(); for(int i = 0; i < size; i++) { // 获取随机位置 int randomPos = random.nextInt(size); // 当前元素与随机元素交换 T temp = list.get(i); list.set(i, list.get(randomPos)); list.set(randomPos, temp); } }
很简单,实现方法也很多,但有更简单的实现方法:
public <T> void shuffle2(List<T> list) { int size = list.size(); Random random = new Random(); for(int i = 0; i < size; i++) { // 获取随机位置 int randomPos = random.nextInt(size); // 当前元素与随机元素交换 Collections.swap(list, i, randomPos); } }
上面使用了Collections的swap方法,该方法会交换两个位置的元素值,不用我们自己写交换代码了,是不是更简单呢?
其实,我想说,还有更更简单的方法,如下:
public <T> void shuffle3(List<T> list) { // 打乱顺序 Collections.shuffle(list); }
这才是我们想要的结果,就这一句话即可打乱一个列表的顺序,不用我们费尽心思的遍历、替换元素了!
现在来测试一下,是不是都能成功实现打乱顺序呢?下面给出完整源代码:
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; /** * 打乱列表中数据元素的三种实现方法 */ public class ShuffleTest { // 打乱列表实现方法1 public <T> void shuffle1(List<T> list) { int size = list.size(); Random random = new Random(); for(int i = 0; i < size; i++) { // 获取随机位置 int randomPos = random.nextInt(size); // 当前元素与随机元素交换 T temp = list.get(i); list.set(i, list.get(randomPos)); list.set(randomPos, temp); } } // 打乱列表实现方法2 public <T> void shuffle2(List<T> list) { int size = list.size(); Random random = new Random(); for(int i = 0; i < size; i++) { // 获取随机位置 int randomPos = random.nextInt(size); // 当前元素与随机元素交换 Collections.swap(list, i, randomPos); } } // 打乱列表实现方法3 public <T> void shuffle3(List<T> list) { // 打乱顺序 Collections.shuffle(list); } // 打印列表 public <T> void print(List<T> list) { for(T t : list) { System.out.print(t + " "); } System.out.println("\n"); } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ShuffleTest st = new ShuffleTest(); List<String> tagClouds = new ArrayList<String>(6); // 一般从数据库中读取,这里仅以测试为目的 tagClouds.add("计算机"); tagClouds.add("Java"); tagClouds.add("编程"); tagClouds.add("C/C++"); tagClouds.add("操作系统"); tagClouds.add("数据库"); System.out.println("原顺序:"); st.print(tagClouds); st.shuffle1(tagClouds); System.out.println("打乱顺序一:"); st.print(tagClouds); st.shuffle2(tagClouds); System.out.println("打乱顺序二:"); st.print(tagClouds); st.shuffle3(tagClouds); System.out.println("打乱顺序三:"); st.print(tagClouds); } }
输出结果如下:
我们一般很少用到shuffle这个方法,那它可以用在什么地方呢?
(1)可以用在程序的“伪装”上 比如我们例子中的标签云,或者是游戏中的打怪、修行、群殴时宝物的分配策略。 (2)可以用在抽奖程序中 比如年会的抽奖程序,先使用shuffle把员工顺序打乱,每个员工的中奖几率就是相等的了,然后就可以抽取第一名、第二名。 (3)可以用在安全传输方面 比如发送端发送一组数据,先随机打乱顺序,然后加密发送,接收端解密,然后自行排序,即可实现即使是相同的数据源,也会产生不同密文的效果,加强了数据的安全性。
http://www.cnblogs.com/lanxuezaipiao/p/3192980.html
import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.springframework.util.StopWatch; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author: tangcheng * @description: * @since: Created in 2018/08/07 11:01 */ @Slf4j public class CollectShuttleTest { /** * 从1000个中去掉100个,总耗时18ms * 混淆后的数据,没有发现明显的问题 */ @Test public void shuffleTest() { List<Integer> total = new ArrayList<>(); for (int i = 0; i < 1000; i++) { total.add(i); } StopWatch stopWatch = new StopWatch("Collections.shuffle()"); int count = 100; List<Integer> winnerList = new ArrayList<>(100); for (int i = 0; i < count; i++) { stopWatch.start("time_" + i); Collections.shuffle(total); int index = total.size() - 1; Integer winner = total.remove(index); winnerList.add(winner); log.info("taskName:{},winner:{}", i, winner); stopWatch.stop(); } log.info("winnerList:{},stopWatch.prettyPrint():{}", winnerList, stopWatch.prettyPrint()); /** * winnerList:[ * 163, 905, 954, 828, 387, 217, 272, 662, 753, 160, * 636, 629, 132, 318, 655, 388, 501, 879, 625, 515, * 339, 897, 497, 959, 819, 654, 71, 984, 356, 256, * 539, 330, 888, 643, 928, 10, 213, 878, 935, 206, * 53, 875, 437, 422, 997, 464, 276, 65, 451, 732, * 432, 154, 385, 955, 161, 719, 352, 383, 37, 853, * 675, 696, 646, 223, 742, 807, 76, 738, 415, 516, * 890, 656, 610, 910, 80, 7, 561, 548, 947, 390, * 949, 236, 382, 338, 112, 240, 162, 642, 754, 571, * 8, 802, 532, 410, 372, 462, 880, 38, 744, 360 * ], * stopWatch.prettyPrint():StopWatch 'Collections.shuffle()': running time (millis) = 18 * ----------------------------------------- * ms % Task name * ----------------------------------------- * 00007 039% time_0 * 00000 000% time_1 * 00000 000% time_2 * 00001 006% time_3 * 00000 000% time_4 * 00000 000% time_5 * 00000 000% time_6 * 00000 000% time_7 * 00000 000% time_8 * 00000 000% time_9 * 00000 000% time_10 * 00000 000% time_11 * 00001 006% time_12 * 00000 000% time_13 * 00000 000% time_14 * 00000 000% time_15 * 00000 000% time_16 * 00000 000% time_17 * 00000 000% time_18 * 00000 000% time_19 * 00000 000% time_20 * 00000 000% time_21 * 00000 000% time_22 * 00000 000% time_23 * 00001 006% time_24 * 00000 000% time_25 * 00000 000% time_26 * 00000 000% time_27 * 00001 006% time_28 * 00000 000% time_29 * 00001 006% time_30 * 00000 000% time_31 * 00000 000% time_32 * 00000 000% time_33 * 00000 000% time_34 * 00000 000% time_35 * 00000 000% time_36 * 00000 000% time_37 * 00000 000% time_38 * 00000 000% time_39 * 00000 000% time_40 * 00001 006% time_41 * 00000 000% time_42 * 00000 000% time_43 * 00000 000% time_44 * 00000 000% time_45 * 00000 000% time_46 * 00000 000% time_47 * 00000 000% time_48 * 00000 000% time_49 * 00000 000% time_50 * 00001 006% time_51 * 00000 000% time_52 * 00000 000% time_53 * 00000 000% time_54 * 00000 000% time_55 * 00000 000% time_56 * 00000 000% time_57 * 00000 000% time_58 * 00000 000% time_59 * 00000 000% time_60 * 00000 000% time_61 * 00000 000% time_62 * 00001 006% time_63 * 00000 000% time_64 * 00000 000% time_65 * 00001 006% time_66 * 00000 000% time_67 * 00000 000% time_68 * 00000 000% time_69 * 00000 000% time_70 * 00000 000% time_71 * 00000 000% time_72 * 00000 000% time_73 * 00000 000% time_74 * 00000 000% time_75 * 00000 000% time_76 * 00001 006% time_77 * 00000 000% time_78 * 00000 000% time_79 * 00000 000% time_80 * 00000 000% time_81 * 00000 000% time_82 * 00000 000% time_83 * 00000 000% time_84 * 00000 000% time_85 * 00000 000% time_86 * 00000 000% time_87 * 00000 000% time_88 * 00000 000% time_89 * 00000 000% time_90 * 00000 000% time_91 * 00001 006% time_92 * 00000 000% time_93 * 00000 000% time_94 * 00000 000% time_95 * 00000 000% time_96 * 00000 000% time_97 * 00000 000% time_98 * 00000 000% time_99 */ } }