Разница между массивами.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- это другой вид объекта.ArrayLists имеют свой собственный, внутренний массив, в котором они хранят свои элементы и могут изменять размеры внутренних массивов и т. д. Оболочка не имеет собственного внутреннего массива, она только распространяет операции массив, данный ему.С другой стороны, если вы впоследствии создадите новый массив как
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);здесь, список возвращается как
Listview, что означает, что он имеет только методы, прикрепленные к этому интерфейсу. Следовательно, почему некоторые методы не допускаются на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)- любое изменение, которое вы делаете с помощью ссылки на список, будет отражено в выходе
Arrays объект (как вы работаете на существующий объект массива с помощью списка ссылок)в первом случае вы создаете новый
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методыLists, которые на самом деле не поддерживают всеListметоды.если бы они назвали метод
asImmutableList, имело бы смысл. Или если бы у них просто был метод, возвращающий фактическоеList(и скопируйте резервный массив), это имело бы смысл. Они решили отдать предпочтение обеим runtime-performance и короткие имена, за счет нарушения как принципа наименьшего Удивление и хорошая практика избеганияUnsupportedOperationExceptions.(кроме того, дизайнеры могли бы сделать
interface ImmutableList, чтобы избежать множестваUnsupportedOperationExceptions.)