打乱list顺序tShuffle实现

2020/09/21 Java

tShuffle实现更改!

目录

传统的打乱list算法和本地算法比较

1.大多数时候大家一般是调用jdk原生提供方法Collections.shuffle(), 就可以轻松实现打乱list。

2.传统上打乱算法类似洗牌,理论上洗牌是有可能出现顺序不变的情况!Collections.shuffle()极端的情况下,是可能顺序不变的。

3.本次方法不是传统意义上的打乱,会保证至少交换一次顺序!基于trove4j的TintArrayList实现,应用时注意自己的业务需求!

1.jdk原生Collections.shuffle()

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();

            //假设rnd.nextInt(i)极端情况每次随机都随到i - 1下标,那么就会导致顺序不变
            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]);
            }
        }
    }

Collections.shuffle()方法极端的情况下,是可能顺序不变的。

2.trove4j的TintArrayList打乱顺序,保证至少交换一次,从而保证一定是乱序

/**
* 打乱list顺序
* @param srcList
* @return
*/
public static TIntArrayList tShuffle(TIntArrayList srcList)
{
    if (null == srcList)
    {
        return null;
    }

    //如果小于1,直接new一个新list返回,防止修改外部源
    int size = srcList.size();
    if (size <= 1)
    {
        return new TIntArrayList(srcList);
    }

    ThreadLocalRandom random = ThreadLocalRandom.current();
    int[] objects = srcList.toArray();
    for (int i = objects.length; i > 1; i--)
    {
        //random.nextInt(i - 1))从i - 1开始,那么至少保证交换一次
        swap(objects, i-1, random.nextInt(i - 1));
    }

    //直接new一个新list返回,防止修改外部源
    TIntArrayList list = new TIntArrayList(size);
    for (int i = 0; i < size; i++)
    {
        list.add(objects[i]);
    }

    return list;
}

/**
* Swaps the two specified elements in the specified array.
*/
private static void swap(int[] arr, int i, int j)
{
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

random.nextInt(i - 1))从i - 1开始,那么可以至少保证交换一次。

该方法是为了符合我们业务需求定制的,不是最高效的,应用时注意自己的业务需求!

Search

    Table of Contents