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

时间:2013-05-25 09:07:25

标签: java list collections

之间有什么区别
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

其中ia是整数数组。

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

当我随机播放列表时,list1不会影响原始数组,list2会影响原始数组。但是list2仍然有些令人困惑。

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

不同
list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

13 个答案:

答案 0 :(得分:187)

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

    Arrays.asList(ia)
    

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

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

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

    new ArrayList<Integer>(Arrays.asList(ia))
    

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

答案 1 :(得分:21)

这是因为ArrayList生成的Arrays.asList()不属于java.util.ArrayList类型。 Arrays.asList()创建的ArrayList类型java.util.Arrays$ArrayList不会延伸java.util.ArrayList,只会延伸{​​{1}}

答案 2 :(得分:8)

List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy

在这种情况下,list1的类型为ArrayList

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

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

ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

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

ArrayList list1 = (ArrayList)Arrays.asList(ia);

答案 3 :(得分:3)

我在这里已经很晚了,无论如何,对于那些寻找答案的人来说,文件参考的解释会更好。

  
      
  1. java.util.Arrays
  2.   
  • 这是一个包含静态方法的实用程序类,可以在给定的数组
  • 上运行
  • asList是一个这样的静态方法,它接受输入数组并返回 java.util.Arrays.ArrayList 的对象,这是一个静态嵌套类,它扩展了AbstractList,它实现了List接口。
  • 所以Arrays.asList(inarray)在输入数组周围返回一个List包装器,但是这个包装器是 java.util.Arrays.ArrayList而不是java.util.ArrayList ,它引用了相同的数组因此,向List包装数组中添加更多元素也会影响orignal,并且我们也无法更改长度。
  
      
  1. java.util.ArrayList
  2.   
  • ArrayList有一堆重载的构造函数

    public ArrayList() - //返回默认容量为10的arraylist

    public ArrayList(Collection c)

    public ArrayList(int initialCapacity)

  • 因此,当我们将Arrays.asList返回的对象(即List(AbstractList))传递给上面的第二个构造函数时,它将创建一个新的动态数组(此数组大小随着我们添加的元素数量增加而不是其容量以及新元素不会影响orignal数组)浅复制原始数组(shallow copy意味着它只复制引用,并不会创建一组与orignal数组相同的新对象)

答案 4 :(得分:3)

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> namesList = Arrays.asList(names);

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> temp = Arrays.asList(names);         

Above Statement在输入数组上添加了包装器。所以像add&amp; amp;删除将不适用于列表引用对象&#39; namesList&#39;。

如果你试图在现有的数组/列表中添加一个元素,那么你将得到&#34;线程中的异常&#34; main&#34; java.lang.UnsupportedOperationException&#34;

以上操作只读或查看。
我们无法在列表对象中执行添加或删除操作。 但

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> listObject = Arrays.asList(names);
java.util.ArrayList<String> list1 = new ArrayList<>(listObject);

在上面的语句中,您创建了一个ArrayList类的具体实例,并将列表作为参数传递。

在这种情况下,方法add&amp; remove将正常工作,因为这两个方法都来自ArrayList类,所以在这里我们不会得到任何UnSupportedOperationException。
在Arraylist对象中进行的更改(方法在arraylist中添加或删除元素)将不会反映到原始java.util.List对象中。

String names[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};

java.util.List < String > listObject = Arrays.asList(names);
java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
    System.out.print("   " + string);
}
list1.add("Alex"); //Added without any exception
list1.remove("Avinash"); //Added without any exception will not make any changes in original list in this case temp object.


for (String string: list1) {
    System.out.print("   " + string);
}
String existingNames[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};
java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); //UnsupportedOperationException

答案 5 :(得分:2)

请注意,在Java 8中,&#39; ia&#39;上面必须是Integer []而不是int []。 int数组的Arrays.asList()返回一个包含单个元素的列表。使用OP的代码片段时,编译器会发现问题,但是某些方法(例如Collections.shuffle())将无法按照您的预期进行操作。

答案 6 :(得分:2)

首先,Arrays类是一个实用程序类,其中不包含任何类。可以在Arrays上运行的实用程序方法(由于Arrays类,否则我们将需要创建自己的方法来对Array对象进行操作)

asList()方法:

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

在第一种情况下,您将创建一个新的list.remove(10);对象(在第二种情况下,将仅创建对现有Array对象的引用,而不会创建一个新的Array对象),因此现在有两个不同的对象: Arraylist对象,另一个是ArrayList对象,并且它们之间没有任何联系(因此,一个对象的更改将不会在另一对象中反映/影响(在情况2 Array和{{1 }}是两个不同的对象)

情况1:

ArrayList

情况2:

Array

答案 7 :(得分:1)

package com.copy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class CopyArray {

    public static void main(String[] args) {
        List<Integer> list1, list2 = null;
        Integer[] intarr = { 3, 4, 2, 1 };
        list1 = new ArrayList<Integer>(Arrays.asList(intarr));
        list1.add(30);
        list2 = Arrays.asList(intarr);
        // list2.add(40); Here, we can't modify the existing list,because it's a wrapper
        System.out.println("List1");
        Iterator<Integer> itr1 = list1.iterator();
        while (itr1.hasNext()) {
            System.out.println(itr1.next());
        }
        System.out.println("List2");
        Iterator<Integer> itr2 = list2.iterator();
        while (itr2.hasNext()) {
            System.out.println(itr2.next());
        }
    }
}

答案 8 :(得分:1)

pip show setuptools | findstr "Version"

此方法返回其自己的List实现。它将数组作为参数并在其上构建方法和属性,因为它不是从数组复制任何数据但使用原始数组这会导致原始数组的更改当您修改Version: 34.1.1 方法返回的列表时。

另一方面,

Arrays.asList()Arrays.asList()类的构造函数,它以列表作为参数并返回独立于列表的ArrayList(Arrays.asList());,即。在这种情况下,ArrayList作为参数传递。 这就是你看到这些结果的原因;

答案 9 :(得分:1)

许多人已经回答了机械细节,但是值得注意的是: 通过Java,这是一个糟糕的设计选择。

Java的asList方法记录为“返回固定大小列表...”。如果获取其结果并调用(例如).add方法,它将抛出一个UnsupportedOperationException。这是不直观的行为!如果某个方法说它返回一个List,则标准的期望是它返回一个支持接口List的方法的对象。开发人员不必记住很多util.List方法中的哪个 创建的List实际上并不支持所有的List方法。

如果他们已将方法命名为asImmutableList,那将是有道理的。或者,如果他们只是让该方法返回实际的List(并复制后备数组),那将是有道理的。他们决定同时支持运行时性能短名称,但要同时违反最小惊喜原则和good-O.O。避免使用UnsupportedOperationException的习惯。

(此外,设计人员可能制作了interface ImmutableList,以避免过多的UnsupportedOperationException。)

答案 10 :(得分:0)

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

在第2行中,Arrays.asList(ia)返回List内定义的内部类对象的Arrays引用,该引用也称为ArrayList,但它是私有的,只扩展{{1} }}。这意味着从AbstractList返回的是与Arrays.asList(ia)不同的类对象。

您不能对第2行使用某些操作,因为new ArrayList<Integer>中的内部私有类不提供这些方法。

看一下这个链接,看看你可以用私有内部类做什么: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Arrays.java#Arrays.ArrayList

第1行创建一个新的Arrays对象,复制你从第2行获得的元素。所以你可以做任何你想做的事情,因为ArrayList提供了所有这些方法。

答案 11 :(得分:0)

差异总结 -

当创建列表而不使用新的运算符Arrays.asList()方法时,它返回Wrapper,这意味着

1。您可以执行添加/更新操作。

2。原始数组中所做的更改也会反映到List中     反之亦然。

答案 12 :(得分:0)

针对某些评论,他们提出了关于Java 8以来Arrays.asList()的行为的问题:

    int[] arr1 = {1,2,3};
    /* 
       Arrays are objects in Java, internally int[] will be represented by 
       an Integer Array object which when printed on console shall output
       a pattern such as 
       [I@address for 1-dim int array,
       [[I@address for 2-dim int array, 
       [[F@address for 2-dim float array etc. 
   */
    System.out.println(Arrays.asList(arr1)); 

    /* 
       The line below results in Compile time error as Arrays.asList(int[] array)
       returns List<int[]>. The returned list contains only one element 
       and that is the int[] {1,2,3} 
    */
    // List<Integer> list1 = Arrays.asList(arr1);

    /* 
       Arrays.asList(arr1) is  Arrays$ArrayList object whose only element is int[] array
       so the line below prints [[I@...], where [I@... is the array object.
    */
    System.out.println(Arrays.asList(arr1)); 

    /* 
     This prints [I@..., the actual array object stored as single element 
     in the Arrays$ArrayList object. 
    */
    System.out.println(Arrays.asList(arr1).get(0));

    // prints the contents of array [1,2,3]
    System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));

    Integer[] arr2 = {1,2,3};
    /* 
     Arrays.asList(arr) is  Arrays$ArrayList object which is 
     a wrapper list object containing three elements 1,2,3.
     Technically, it is pointing to the original Integer[] array 
    */
    List<Integer> list2 = Arrays.asList(arr2);

    // prints the contents of list [1,2,3]
    System.out.println(list2);