Arrays.asList(array)和new ArrayList <Integer>(Arrays.asList(array))之间的区别

Din*_*mar 101 java collections list

有什么区别

1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);
Run Code Online (Sandbox Code Playgroud)

哪里ia是整数数组.

我开始知道不允许进行某些操作list2.为什么会这样?它是如何存储在内存中的(引用/复制)?

当我洗牌时,list1不会影响原始数组,但list2确实如此.但仍list2有些令人困惑.

如何ArrayList列出列表与创建新列表不同ArrayList

list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Run Code Online (Sandbox Code Playgroud)

Pet*_*lák 194

  1. 首先,让我们看看它的作用:

    Arrays.asList(ia)
    
    Run Code Online (Sandbox Code Playgroud)

    它接受一个数组ia并创建一个实现的包装器List<Integer>,这使得原始数组可用作列表.没有复制任何内容,只创建了一个包装器对象.列表包装器上的操作将传播到原始数组.这意味着如果你改组列表包装器,原始数组也会被洗牌,如果你覆盖一个元素,它会被原始数组覆盖,等等.当然,List包装器上不允许进行某些操作,如添加或从列表中删除元素,您只能读取或覆盖元素.

    请注意,列表包装器不会扩展ArrayList- 它是一种不同类型的对象.ArrayLists有自己的内部数组,它们存储它们的元素,并且能够调整内部数组等.包装器没有自己的内部数组,它只将操作传播给给定的数组.

  2. 另一方面,如果您随后创建一个新数组

    new ArrayList<Integer>(Arrays.asList(ia))
    
    Run Code Online (Sandbox Code Playgroud)

    然后你创建新的ArrayList,这是原始的一个完整,独立的副本.虽然在这里您也使用了包装器Arrays.asList,但它仅在构造新的时使用ArrayList,之后进行垃圾收集.这个新结构ArrayList完全独立于原始数组.它包含相同的元素(原始数组和这个新ArrayList引用都在内存中使用相同的整数),但它创建了一个新的内部数组,用于保存引用.因此,当您对其进行随机播放,添加,删除元素等时,原始数组将保持不变.

  • @Dineshkumar包装器是一种设计模式,它将类的一个接口转换为另一个接口.请参阅[包装模式](https://en.wikipedia.org/wiki/Adapter_pattern)文章.| 你需要在哪里翻转?我建议使用`List <Integer>`作为变量类型(或方法参数等).这使您的代码更通用,您可以根据需要轻松切换到另一个`List`实现,而无需重写大量代码. (8认同)

Chr*_*ris 24

嗯,这是因为ArrayList从产生Arrays.asList()的类型是不是java.util.ArrayList.Arrays.asList()创建一个ArrayList类型的java.util.Arrays$ArrayList不延伸java.util.ArrayList,但仅延伸java.util.AbstractList


chr*_*her 9

List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
Run Code Online (Sandbox Code Playgroud)

在这种情况下,list1是类型ArrayList.

List<Integer> list2 = Arrays.asList(ia);
Run Code Online (Sandbox Code Playgroud)

这里,列表作为List视图返回,这意味着它只有附加到该接口的方法.因此,为什么不允许某些方法list2.

ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Run Code Online (Sandbox Code Playgroud)

在这里,您正在创建一个新的ArrayList.你只是在构造函数中传递一个值.这不是铸造的例子.在投射中,它可能看起来更像这样:

ArrayList list1 = (ArrayList)Arrays.asList(ia);
Run Code Online (Sandbox Code Playgroud)


irf*_*fan 5

首先,Arrays 类是一个实用程序类,其中包含许多对 Arrays 进行操作的实用程序方法(感谢 Arrays 类。否则,我们需要创建自己的方法来操作 Array 对象)

asList() 方法:

  1. asListmethod 是类的实用方法之一Array,它是一个静态方法,这就是为什么我们可以通过其类名来调用该方法(例如Arrays.asList(T...a)
  2. 现在问题来了。请注意,此方法不会创建新ArrayList对象。它只是返回对现有对象的 List 引用Array(所以现在使用方法后,会创建asList对现有对象的两个引用)Array
  3. 这就是原因。所有对对象进行操作的方法List可能无法使用引用来处理此 Array 对象List。例如,Arrays 的大小是固定长度的,因此显然不能Array使用此List引用从对象添加或删除元素(如list.add(10)list.remove(10);。否则它将抛出 UnsupportedOperationException)。
  4. 您使用列表引用所做的任何更改都将反映在现有的Arrays 对象中(因为您正在使用列表引用对现有 Array 对象进行操作)

在第一种情况下,您正在创建一个新Arraylist对象(在第二种情况下,仅创建对现有 Array 对象的引用,而不是新ArrayList对象),因此现在有两个不同的对象。一个是Array对象,另一个是ArrayList对象,它们之间没有任何联系(因此一个对象中的更改不会反映/影响另一个对象(即,在情况 2 中,ArrayArraylist是两个不同的对象)

情况1:

Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  // new ArrayList object is created , no connection between existing Array Object
list1.add(5);
list1.add(6);
list1.remove(0);
list1.remove(0);
System.out.println("list1: " + list1);
System.out.println("Array: " + Arrays.toString(ia));
Run Code Online (Sandbox Code Playgroud)

案例2:

Integer [] ia = {1,2,3,4};
System.out.println("Array: " + Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia); // Creates only a (new) List reference to the existing Array object (and NOT a new ArrayList Object)
//  list2.add(5); // It will throw java.lang.UnsupportedOperationException - invalid operation (as Array size is fixed)
list2.set(0,10);  // Making changes in the existing Array object using the List reference - valid 
list2.set(1,11); 
ia[2]=12;     // Making changes in the existing Array object using the Array reference - valid
System.out.println("list2: " + list2);
System.out.println("Array: " + Arrays.toString(ia));
Run Code Online (Sandbox Code Playgroud)