В чем разница между
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));
java
list
collections
Dineshkumar
источник
источник
Lists.newArrayList(ia)
делает независимую копию, как и в первом варианте. Это просто более общий характер, и на него лучше смотреть.Ответы:
Сначала давайте посмотрим, что это делает:
Он принимает массив
ia
и создает оболочку, которая реализуетList<Integer>
, что делает исходный массив доступным в виде списка. Ничего не копируется и все, создается только один объект-оболочка. Операции с оболочкой списка распространяются на исходный массив. Это означает, что если вы перетасовываете оболочку списка, перетасовывается и исходный массив, если вы перезаписываете элемент, он перезаписывается в исходном массиве и т. Д. Конечно, некоторыеList
операции с оболочкой не разрешены, такие как добавление или удаляя элементы из списка, вы можете только читать или перезаписывать элементы.Обратите внимание, что оболочка списка не расширяется
ArrayList
- это объект другого типа.ArrayList
s имеют свой собственный внутренний массив, в котором они хранят свои элементы, и могут изменять размер внутренних массивов и т. д. Обертка не имеет собственного внутреннего массива, она только передает операции в массив, переданный ей.С другой стороны, если вы впоследствии создадите новый массив как
затем вы создаете новую
ArrayList
, которая является полной независимой копией оригинала. Хотя здесь вы также создаете оболочку usingArrays.asList
, она используется только во время создания новогоArrayList
и после этого собирается сборщиком мусора. Структура этого новогоArrayList
полностью независима от исходного массива. Он содержит те же элементы (и исходный массив, и эта новаяArrayList
ссылка на одни и те же целые числа в памяти), но создает новый внутренний массив, содержащий ссылки. Поэтому, когда вы перетасовываете его, добавляете, удаляете элементы и т. Д., Исходный массив не изменяется.источник
List<Integer>
для ваших типов переменных (или аргументов метода и т. Д.). Это делает ваш код более универсальным, и вы можете легко переключиться на другуюList
реализацию по мере необходимости без необходимости переписывать много кода.Это ж потому, что
ArrayList
результатArrays.asList()
не того типаjava.util.ArrayList
.Arrays.asList()
создаетArrayList
тип,java.util.Arrays$ArrayList
который не расширяется,java.util.ArrayList
а только расширяетсяjava.util.AbstractList
источник
В данном случае
list1
типArrayList
.Здесь список возвращается как
List
представление, то есть в нем есть только методы, прикрепленные к этому интерфейсу. Следовательно, почему некоторые методы не разрешеныlist2
.Здесь вы СОЗДАЕТЕ новый
ArrayList
. Вы просто передаете ему значение в конструкторе. Это не пример кастинга. В кастинге это могло бы выглядеть примерно так:источник
Я здесь довольно поздно, в любом случае почувствовал, что объяснение со ссылками на документы будет лучше для тех, кто ищет ответ.
ArrayList имеет кучу перегруженных конструкторов
public ArrayList () - // возвращает ArrayList с емкостью по умолчанию 10
общедоступный ArrayList (Коллекция c)
общедоступный ArrayList (int initialCapacity)
Поэтому, когда мы передаем возвращаемый объект Arrays.asList, то есть List (AbstractList), второму конструктору выше, он создаст новый динамический массив (этот размер массива увеличивается, когда мы добавляем больше элементов, чем его емкость, а также новые элементы не повлияют на исходный массив ) неглубокое копирование исходного массива ( мелкое копирование означает, что оно копирует только ссылки и не создает новый набор тех же объектов, что и в исходном массиве)
источник
или
Вышеуказанный оператор добавляет оболочку к входному массиву. Таким образом, такие методы, как add и remove, не будут применяться к объекту ссылки на список «namesList».
Если вы попытаетесь добавить элемент в существующий массив / список, вы получите «Исключение в потоке» main «java.lang.UnsupportedOperationException».
Вышеупомянутая операция доступна только для чтения или просмотра.
Мы не можем выполнить операцию добавления или удаления в объекте списка. Но
или
В приведенном выше заявлении вы создали конкретный экземпляр класса ArrayList и передали список в качестве параметра.
В этом случае метод add & remove будет работать правильно, поскольку оба метода относятся к классу ArrayList, поэтому здесь мы не получим исключения UnSupportedOperationException.
Изменения, внесенные в объект Arraylist (метод добавления или удаления элемента в / из Arraylist), не будут отражены в исходном объекте java.util.List.
источник
Прежде всего, класс Arrays - это служебный класс, который не содержит файлов. служебных методов для работы с массивами (благодаря классу Arrays, в противном случае нам пришлось бы создавать собственные методы для работы с объектами массивов)
asList () метод:
asList
Метод является одним из служебных методовArray
класса, это статический метод, поэтому мы можем вызывать этот метод по имени его класса (напримерArrays.asList(T...a)
)ArrayList
объект, он просто возвращает ссылку List на существующийArray
объект (так что теперь после использованияasList
методаArray
создаются две ссылки на существующий объект)List
объектом, могут НЕ работать с этим объектом Array, используяList
ссылку, например,Array
размер s фиксирован по длине, поэтому вы, очевидно, не можете добавлять или удалять элементы изArray
объекта, используя этуList
ссылку (например,list.add(10)
илиlist.remove(10);
иначе он вызовет исключение UnsupportedOperationException)Array
объекта s (поскольку вы работаете с существующим объектом Array, используя ссылку на список)В первом случае вы создаете новый
Arraylist
объект (во втором случае создается только ссылка на существующий объект Array, но не новыйArrayList
объект), поэтому теперь есть два разных объекта: одинArray
объект, а другойArrayList
объект, и нет связи между ними (поэтому изменения в одном объекте не будет отражаться / затрагиваться в другом объекте (то есть в случае 2Array
иArraylist
это два разных объекта)Случай 1:
случай 2:
источник
Многие люди уже ответили на механические детали, но стоит отметить: это плохой выбор дизайна со стороны Java.
asList
Метод Java задокументирован как «Возвращает список фиксированного размера ...». Если вы возьмете его результат и вызовете (скажем).add
метод, он выдаст файлUnsupportedOperationException
. Это неинтуитивное поведение! Если метод сообщает, что возвращает aList
, стандартное ожидание состоит в том, что он возвращает объект, который поддерживает методы интерфейсаList
. Разработчику не нужно запоминать, какой из бесчисленныхutil.List
методов создаетList
s, которые фактически не поддерживают всеList
методы.Если бы они назвали метод
asImmutableList
, это имело бы смысл. Или, если бы они просто вернули реальный методList
(и скопировали резервный массив), это имело бы смысл. Они решили отдать предпочтение как производительности во время выполнения, так и коротким именам, за счет нарушения как принципа наименьшего неожиданности, так и хорошей OO-практики избеганияUnsupportedOperationException
s.(Кроме того, дизайнеры могли сделать a
interface ImmutableList
, чтобы избежать множестваUnsupportedOperationException
s.)источник
Обратите внимание, что в Java 8 указанное выше 'ia' должно быть Integer [], а не int []. Arrays.asList () массива int возвращает список с одним элементом. При использовании фрагмента кода OP компилятор обнаружит проблему, но некоторые методы (например, Collections.shuffle ()) не смогут сделать то, что вы ожидаете.
источник
источник
Arrays.asList()
этот метод возвращает свою собственную реализацию List. Он принимает массив в качестве аргумента и строит методы и атрибуты поверх него, поскольку он не копирует какие-либо данные из массива, а использует исходный массив, это вызывает изменение в исходном массиве при изменении список, возвращаемый
Arrays.asList()
методом.с другой стороны.
ArrayList(Arrays.asList());
является конструкторомArrayList
класса, который принимает список в качестве аргумента и возвращаетArrayList
независимый от списка, т.е.Arrays.asList()
в данном случае передается как аргумент. вот почему вы видите эти результаты;источник
В строке 2
Arrays.asList(ia)
возвращаетсяList
ссылка на объект внутреннего класса, определенный внутри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
предоставляет все эти методы.источник
Резюме разницы -
когда список создается без использования нового метода оператора Arrays.asList (), он возвращает Wrapper, что означает
1. вы можете выполнить операцию добавления / обновления.
2. Изменения, сделанные в исходном массиве, также будут отражены в списке и наоборот.
источник
В ответ на некоторые комментарии, задающие вопросы о поведении Arrays.asList () начиная с Java 8:
источник