关于 Arrays.asList()与Collections.shuffle()使用时的坑

2022-02-09 16:09:41 浏览数 (1)

今天使用Arrays.asList()这个方法碰见一个问题记录一下。

引入:

Java.util.Collections类下有一个静态的shuffle()方法,如下:

1)static voidshuffle(List<?> list) 使用默认随机源对列表进行置换,所有置换发生的可能性都是大致相等的。 2)static voidshuffle(List<?> list, Random rand) 使用指定的随机源对指定列表进行置换,所有置换发生的可能性都是大致相等的,假定随机源是公平的。

java.util.Arrays类中有一个静态的asList()方法,如下: public static List asList(T… a) 返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会“直接写”到数组。) 此方法还提供了一个创建固定长度的列表的便捷方法,该列表被初始化为包含多个元素:

代码语言:javascript复制
 List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

废话少说,我们来看代码吧,

代码语言:javascript复制
public static void main(String[] args) {
        Integer[] temp={1,2,3,45,6,6,456,7,8};

        List<Integer> list= Arrays.asList(temp);
        System.out.println("list:更改前:" list);
        Collections.shuffle(list);
        System.out.println("list:更改后:" list);
        System.out.println("---------------");

        List<Integer> list2= Arrays.asList(temp);
        System.out.println("list2:更改前list:" list);
        System.out.println("list2:更改前list2:" list2);
        Collections.shuffle(list2);
        System.out.println("list2:更改后list:" list);
        System.out.println("list2:更改前list:" list2);
    }

其打印结果为:

什么鬼东西,打印结果表示两个List内容相同?? 难道是这两个list的地址相同了吗? 随后进行比较:

地址不一致?那么是什么情况造成这种结果呢? 通过查阅资料发现。

如果给定一个整型数组,用Arrays.asList()方法将其转化为一个集合类,有两种途径:

1)用List list=ArrayList(Arrays.asList(temp)),用shuffle()打乱不会改变底层数组的顺序。

2)用List list=Arrays.aslist(temp),然后用shuffle()打乱会改变底层数组的顺序。

这么一看,清楚明了,是我错误的使用了Arrays.asList()造成的问题。

代码例子如下:

代码语言:javascript复制
 public static void main(String[] args) {
        Integer[] temp={1,2,3,45,6,6,456,7,8};
        List<Integer> list=Arrays.asList(temp);

        System.out.println("list:更改前" list);
        Collections.shuffle(list);
        System.out.println("list:更改后" list);
        System.out.println("---------------");

        List<Integer> list2= Arrays.asList(temp);

        System.out.println("list2:更改前" list2);
        System.out.println("list2:更改前list" list);
        Collections.shuffle(list2);
        System.out.println("list2:更改后" list2);
        System.out.println("list2:更改前list" list);

        System.out.println("---------------");
        List<Integer> list3= new ArrayList<>(Arrays.asList(temp));
        System.out.println("list3:更改前list" list);
        System.out.println("list3:更改前list2" list2);
        System.out.println("list3:更改前list3" list3);
        Collections.shuffle(list3);
        System.out.println("list3:更改后list" list);
        System.out.println("list3:更改后list2" list2);
        System.out.println("list3:更改后list3" list3);
    }

运行结果如下:

同过上述代码可以更加清晰的看出来。两种数组转List的方法造成不同的效果。

深入了解一下Arrays.asList()
代码语言:javascript复制
 public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

此处需要注意,asList()返回的是ArrayList并不是java.util包下的,而是java.util.Arrays.ArrayList

我们在来看看java.util.Arrays.ArrayList的结构:

代码语言:javascript复制
 private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable{
        .....
        }

我们从源码中可以看出,该ArrayList只是实现了toArraygetsetindexOf等方法,并没有实现add()remove()方法,而是直接使用它的父类AbstractList的相应方法。 我们来看一下,他的父类AbstractList中关于addremove,进行了什么操作。

代码语言:javascript复制
public void add(int index, @libcore.util.NullFromTypeParam E element) { 
	throw new RuntimeException("Stub!");
}

@libcore.util.NullFromTypeParam public E remove(int index) { 
	throw new RuntimeException("Stub!");
}

可以得知,我们直接使用Arrays.asList()获取到的List,然后进行addremove操作是时会发生异常的。

0 人点赞