之间有什么区别
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));
答案 0 :(得分:187)
首先,让我们看看它的作用:
Arrays.asList(ia)
它需要一个数组ia
并创建一个实现List<Integer>
的包装器,这使得原始数组可用作列表。没有复制任何内容,只创建了一个包装器对象。列表包装器上的操作将传播到原始数组。这意味着如果你改组列表包装器,原始数组也会被洗牌,如果你覆盖一个元素,它会被原始数组覆盖,等等。当然,一些List
操作不允许在包装器,就像在列表中添加或删除元素一样,您只能读取或覆盖元素。
请注意,列表包装器不会扩展ArrayList
- 它是一种不同类型的对象。 ArrayList
有自己的内部数组,它们存储它们的元素,并且能够调整内部数组的大小等。包装器没有自己的内部数组,它只将操作传播给给定的数组。它
另一方面,如果您随后创建一个新数组
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)
我在这里已经很晚了,无论如何,对于那些寻找答案的人来说,文件参考的解释会更好。
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
方法是Array
类的实用方法之一,它是静态方法,这就是为什么我们可以通过其类名(例如Arrays.asList(T...a)
)来调用此方法ArrayList
对象,它只会返回对现有Array
对象的List引用(因此现在使用asList
之后方法,将创建对现有Array
对象的两个引用)List
引用,对List
对象进行操作的所有方法可能不适用于此Array对象,例如
例如,Array
的大小是固定长度的,因此您显然无法使用此Array
引用(例如List
或{{1 }}否则会抛出UnsupportedOperationException)list.add(10)
对象中(因为您正在使用列表引用对现有Array对象进行操作)在第一种情况下,您将创建一个新的list.remove(10);
对象(在第二种情况下,将仅创建对现有Array对象的引用,而不会创建一个新的Array
对象),因此现在有两个不同的对象: Arraylist
对象,另一个是ArrayList
对象,并且它们之间没有任何联系(因此,一个对象的更改将不会在另一对象中反映/影响(在情况2 Array
和{{1 }}是两个不同的对象)
ArrayList
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);