zoukankan      html  css  js  c++  java
  • JDK之集合乱序源码分析

    在JAVA的JDK中Collections类提供了shuffle方法用来对给定的集合参数进行乱序重排,之前面试也被问到过类似的问题,看了一下JDK的源码实现做个记录

    1. 方法签名:

      Collections.shuffle方法提供了两个重载的形式分别为:

    1. public static void shuffle(List<?> list)
    2. public static void shuffle(List<?> list, Random rnd)

    在实现上,第一个方法中new了Random对象,然后调用第二个方法,所以我们来看第二重载形式的实现。全部代码如下:

    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]);
                }
            }
        }

    代码解释:

    SHUFFLE_THRESHOLD 为Collections类中的静态变量,类型为整形,默认为5
    if判断中,首先判断要乱序的集合大小,如果集合大小<5,或者集合类型实现了RandomAccess接口,则直接调用集合交换方法。

    RandomAccess是一个空接口,个人的理解和Serializable接口一样,起到一个标识的作用,在这里标识集合类是否支持随机访问。

    如果支持则随机访问,或者元素个数<5,则直接调用集合交换的swap方法来交换元素(毕竟即使集合不支持RandomAccess,5个

    之内的元素交换也不会影响什么性能)。

    再看一下集合元素交换的方法:

    public static void swap(List<?> list, int i, int j) {
            final List l = list;
            l.set(i, l.set(j, l.get(i)));
    }

    就这么两行代码,不过这里有一点没看懂的是:为什么要声明一个final类型的List来接收参数中的List对象?不明白

    交换的规则也很简单,变量 i 是循环内获取的集合的size值-1,也就是集合的最后一个元素,将最后一个元素的值

    设置为集合中位置 j 的值,j 的值是random.nextInt(i)来随机获取的集合中的某个位置索引。

    所以交换规则就是:

      循环,每次将数组的最后一个元素和一个随机获取到的元素进行交换。

    再来看else分支中:

      能进到else分支,说明集合对象没有实现RandomAccess接口,比如LinkedList没有实现RandomAccess,因为

    数据结构的特性,如果访问LinkedList中的元素只能遍历,如果元素多,访问的元素还靠后,访问性能很差,所以JDK在这里

    将集合首先转为数组,然后调用数组的元素交换方法,交换规则和之前的规则一样。因为数组有下标,支持随机访问,

    所以这样乱序会提高性能。

    private static void swap(Object[] arr, int i, int j) {
        Object tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    数组元素交换方法如上。

  • 相关阅读:
    Celery的使用
    python中使用redis
    Redis基础
    版本控制器git
    day 74作业
    Djangorestfromwork作业1
    Django rest-framework的jwt认证
    Django --form验证
    cx-oracle-------------------安装
    排序算法
  • 原文地址:https://www.cnblogs.com/leemz-coding/p/7448595.html
Copyright © 2011-2022 走看看