Разница между массивами.asList (массив) и новый ArrayList (массивы.asList(массив))
в чем разница между
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));
12 ответов:
во-первых, давайте посмотрим, что это:
Arrays.asList(ia)
он принимает массив
ia
и создает оболочку, которая реализуетList<Integer>
, что делает исходный массив доступным в виде списка. Ничего не копируется и все, только один объект-оболочка создается. Операции в оболочке списка распространяются на исходный массив. Это означает, что при перетасовке оболочки списка исходный массив также перетасовывается, если вы перезаписываете элемент, он перезаписывается в исходный массив и т. д. Конечно, некоторыеList
операции не разрешены на оболочке, например добавление или удаление элементов из списка, вы можете только читать или перезаписывать элементы.обратите внимание, что список обертка не распространяется
ArrayList
- это другой вид объекта.ArrayList
s имеют свой собственный, внутренний массив, в котором они хранят свои элементы и могут изменять размеры внутренних массивов и т. д. Оболочка не имеет собственного внутреннего массива, она только распространяет операции массив, данный ему.С другой стороны, если вы впоследствии создадите новый массив как
new ArrayList<Integer>(Arrays.asList(ia))
затем вы создаете новый
ArrayList
, который является полной, независимой копией оригинала. Хотя здесь вы создаете обертку с помощьюArrays.asList
кроме того, он используется только во время строительства новогоArrayList
и после этого собирается мусор. Структура этого новогоArrayList
полностью не зависит от исходного массива. Он содержит те же элементы (как исходный массив, так и этот новыйArrayList
ссылаться на те же целые числа в памяти), но он создает новый, внутренний массив, который содержит ссылки. Поэтому, когда вы перетасовываете его, добавляете, удаляете элементы и т. д., исходный массив не изменяется.
Ну это потому что
ArrayList
в результатеArrays.asList()
не относится к типуjava.util.ArrayList
.Arrays.asList()
создаетArrayList
типаjava.util.Arrays$ArrayList
который не распространяетсяjava.util.ArrayList
но только расширяетjava.util.AbstractList
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
в этом случае
list1
типаArrayList
.List<Integer> list2 = Arrays.asList(ia);
здесь, список возвращается как
List
view, что означает, что он имеет только методы, прикрепленные к этому интерфейсу. Следовательно, почему некоторые методы не допускаются наlist2
.ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
здесь, вы создаете новый
ArrayList
. Вы просто передаете ему значение в конструкторе. Это не пример кастинга. В кастинге это может выглядеть примерно так:ArrayList list1 = (ArrayList)Arrays.asList(ia);
Я довольно поздно здесь, в любом случае чувствовал, что объяснение со ссылками на doc было бы лучше для кого-то, кто ищет ответ.
- это служебный класс с кучей статических методов для работы на данном массиве
- asList является одним из таких статических методов, который принимает входной массив и возвращает объект java.утиль.Матрицы.ArrayList что является статический вложенный класс, который расширяет AbstractList, который inturn реализует интерфейс списка.
- Так Массивы.asList (inarray) возвращает обертку списка вокруг входного массива, но эта обертка java.утиль.Матрицы.ArrayList, а не java.утиль.ArrayList и это относится к одному и тому же массиву, поэтому добавление большего количества элементов в список обернутого массива также повлияет на исходный, а также мы не можем изменить длину.
ArrayList имеет кучу перегруженных конструкторов
public ArrayList () - / / возвращает arraylist с емкостью по умолчанию 10
public ArrayList (коллекция c)
public ArrayList (int initialCapacity)
Итак, когда мы передаем массивы.asList возвращает объект т. е. List (AbstractList) во второй конструктор выше, он создаст новый динамический массив (этот размер массива увеличивается по мере добавления большего количества элементов, чем его емкость, а также новые элементы не будут влиять на исходный массив) неглубокое копирование исходного массива (мелкая копия означает, что он копирует только ссылки и не создает новый набор тех же объектов, что и в исходном массиве)
обратите внимание, что в Java 8 'ia' выше должно быть Integer [], а не int[]. Матрицы.asList() массива int возвращает список с одним элементом. При использовании фрагмента кода OP компилятор поймает проблему, но некоторые методы (например, коллекции.shuffle ()) будет молча не делать то, что вы ожидаете.
Arrays.asList()
этот метод возвращает свою собственную реализацию List.It принимает массив в качестве аргумента и строит методы и атрибуты поверх него, так как он не копирует какие-либо данные из массива, но использует исходный массив это вызывает изменение исходного массива при изменении списка, возвращаемого
Arrays.asList()
метод.С другой стороны.
ArrayList(Arrays.asList());
является конструкторомArrayList
класс, который принимает список в качестве аргумента и возвращаетArrayList
это независимо от списка ie.Arrays.asList()
в этом случае передается как аргумент. вот почему вы видите эти результаты;
String names[] = new String[]{"Avinash","Amol","John","Peter"}; java.util.List<String> namesList = Arrays.asList(names); or String names[] = new String[]{"Avinash","Amol","John","Peter"}; java.util.List<String> temp = Arrays.asList(names); Above Statement adds the wrapper on the input array. So the methods like add & remove will not be applicable on list reference object 'namesList'. If you try to add an element in the existing array/list then you will get "Exception in thread "main" java.lang.UnsupportedOperationException". The above operation is readonly or viewonly. <br> We can not perform add or remove operation in list object. But String names[] = new String[]{"Avinash","Amol","John","Peter"}; java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names)); or String names[] = new String[]{"Avinash","Amol","John","Peter"}; java.util.List<String> listObject = Arrays.asList(names); java.util.ArrayList<String> list1 = new ArrayList<>(listObject); In above statement you have created a concrete instance of an ArrayList class and passed a list as a parameter. In this case method add & remove will work properly as both methods are from ArrayList class so here we won't get any UnSupportedOperationException. Changes made in Arraylist object (method add or remove an element in/from an arraylist) will get not reflect in to original java.util.List object. 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
прежде всего класс массивов-это служебный класс, который содержит no. утилиты для работы с массивами (благодаря классу Arrays в противном случае нам пришлось бы создавать собственные методы для работы с объектами массива)
метод asList ():
asList
метод является одним из полезных методовArray
класс, это статический метод вот почему мы можем назвать этот метод по его имени класса (напримерArrays.asList(T...a)
)- теперь вот поворот, пожалуйста, обратите внимание что этот метод не создает новый
ArrayList
"объект", он просто возвращает ссылку на список существующихArray
объект (так что теперь после использованияasList
метод, две ссылки на существующиеArray
объект создается)- и это причина, все методы, которые работают на
List
объект, может не работать на этом объекте массива с помощьюList
ссылка например,Array
размер s фиксирован по длине, поэтому вы, очевидно, не можете добавлять или удалять элементы изArray
объект с помощью этогоList
ссылка (напримерlist.add(10)
илиlist.remove(10);
иначе он бросит UnsupportedOperationException)- любое изменение, которое вы делаете с помощью ссылки на список, будет отражено в выходе
Array
s объект (как вы работаете на существующий объект массива с помощью списка ссылок)в первом случае вы создаете новый
Arraylist
объект (во 2-м случае создается только ссылка на существующий объект массива, но не новый
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy 2.List<Integer> list2 = Arrays.asList(ia);
в строке 2,
Arrays.asList(ia)
возвращает aList
ссылка на объект внутреннего класса, определенный вArrays
, который также называютArrayList
но является частным и только расширяетAbstractList
. Это означает, что вернулся изArrays.asList(ia)
это объект класса, отличный от того, что вы получаете отnew ArrayList<Integer>
.вы не можете использовать некоторые операции в строке 2, поскольку внутренний класс внутри
Arrays
не предоставляет эти методы.взгляните на эту ссылку и посмотрите, что вы можете сделать с частным внутренним классом: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Arrays.java#Arrays.ArrayList
строка 1 создает новый
ArrayList
копирование элементов объекта из того, что вы получаете из строки 2. Так что вы можете делать все, что вы хотите, так какjava.util.ArrayList
предоставляет все эти методы.
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()); } } }
многие люди уже ответили на механические детали, но стоит отметить: Это плохой выбор дизайна, Java.
Java
asList
метод документируется как " возвращает a фиксированного размера список...". Если вы берете его результат и звонить (допустим).add
метод, он выдаетUnsupportedOperationException
. Это неинтуитивное поведение! Если метод возвращаетList
, стандартное ожидание заключается в том, что он возвращает объект, который поддерживает методы интерфейсаList
. Разработчик не должен запоминать , который из многочисленныхutil.List
методыList
s, которые на самом деле не поддерживают всеList
методы.если бы они назвали метод
asImmutableList
, имело бы смысл. Или если бы у них просто был метод, возвращающий фактическоеList
(и скопируйте резервный массив), это имело бы смысл. Они решили отдать предпочтение обеим runtime-performance и короткие имена, за счет нарушения как принципа наименьшего Удивление и хорошая практика избеганияUnsupportedOperationException
s.(кроме того, дизайнеры могли бы сделать
interface ImmutableList
, чтобы избежать множестваUnsupportedOperationException
s.)