你会用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
         */
    }


}

 

posted @ 2016-07-26 09:43  沧海一滴  阅读(564)  评论(0编辑  收藏  举报