Инициализация ArrayList эквивалентна инициализации массива

Я знаю, что вы можете инициализировать массив во время создания экземпляра следующим образом:

String[] names = new String[] {"Ryan", "Julie", "Bob"};

Есть ли способ сделать то же самое с ArrayList? Или мне нужно добавить содержимое индивидуально с помощью array.add()?


person Jonathan    schedule 03.05.2010    source источник


Ответы (7)


Arrays.asList может помочь здесь:

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
person meriton    schedule 03.05.2010
comment
Стоит упомянуть, что если вам строго не нужен ArrayList, вероятно, лучше просто использовать List, возвращаемый Arrays#asList. - person maerics; 04.05.2010
comment
@maerics, также стоит упомянуть, что Arrays.asList() возвращает неизменяемую коллекцию. :) - person Konstantin Yovkov; 09.10.2013
comment
Это вызовет ошибку компиляции. Метод asList (Object []) в типе Arrays не применим для аргументов (int, int, int, int, int, int, int). - person R K; 20.01.2014
comment
Фактическая реализация должна быть новым ArrayList ‹Integer› (Arrays.asList (new Object [] {1,2,3,5,8,13,21})); - person R K; 20.01.2014
comment
@RK: С каким компилятором? Мое затмение прекрасно его компилирует ... - person meriton; 20.01.2014
comment
@meriton: я установил уровень компилятора, и JRE указал на 1.5 ... - person R K; 21.01.2014
comment
@RK: В моем eclipse он по-прежнему компилируется с совместимостью Java 5 с JRE 6. Учитывая, что подпись метода не изменилась с JRE 5, я сомневаюсь, что JRE имеет значение. Как бы то ни было, к тому времени, когда я написал этот ответ, Java 5 перестала существовать. (вы на самом деле еще не пользуетесь им, не так ли?) - person meriton; 22.01.2014
comment
Список, возвращаемый Arrays.asList(), НЕ нельзя изменить, @kocko. Он имеет фиксированный размер, но вы можете изменить ссылки, чтобы они указывали на совершенно другие объекты, такие как Arrays.asList(...).set(0,new String("new string")). Этот код будет работать и установит для первого элемента списка объект String со значением new string. Фактически, он записывает данные в собственный массив! Определенно нельзя изменить. - person Jason; 19.04.2014
comment
Почему люди никогда не упоминают в своих сообщениях правильное выражение import / include / require? - person Tomáš Zato - Reinstate Monica; 09.02.2016
comment
Потому что хорошо настроенная среда IDE будет писать импорт за вас, пока существует единственный соответствующий класс, как здесь. - person meriton; 10.02.2016
comment
@KonstantinYovkov ... что полностью находится в рамках контракта объекта List - person forresthopkinsa; 14.08.2017
comment
Прекрасно работает! - person Mert Kahraman; 21.09.2018

да.

new ArrayList<String>(){{
   add("A");
   add("B");
}}

На самом деле это создает класс, производный от ArrayList<String> (это делает внешний набор фигурных скобок), а затем объявляет статический инициализатор (внутренний набор фигурных скобок). На самом деле это внутренний класс содержащего класса, поэтому он будет иметь неявный указатель this. Это не проблема, если вы не хотите сериализовать его или не ожидаете, что внешний класс будет собирать мусор.

Я понимаю, что Java 7 предоставит дополнительные языковые конструкции Делай именно то, что хочешь.

РЕДАКТИРОВАТЬ: последние версии Java предоставляют более удобные функции для создания таких коллекций, и их стоит изучить выше (предоставлено до этих версий)

person Brian Agnew    schedule 03.05.2010
comment
Наверное, потому, что люди не знают, что это возможно. На самом деле это мой любимый способ инициализации карт и других более сложных коллекций, но для списков я предпочитаю Arrays.asList. - person nicerobot; 04.05.2010
comment
Не мой голос против, но я считаю это довольно неприятным злоупотреблением анонимными классами. По крайней мере, вы не пытаетесь выдать это за особенность ... - person Michael Borgwardt; 04.05.2010
comment
Плохо, потому что создает анонимный класс. - person Steve Kuo; 04.05.2010
comment
Я не считаю, что создание анонимного класса плохо само по себе. Однако вы должны знать об этом. - person Brian Agnew; 08.05.2010
comment
Я предполагаю, что он продолжает получать отрицательные голоса, потому что он делает именно то, чего OP хотел избежать: использование add () для каждого элемента. - person WXB13; 14.01.2014
comment
Будьте осторожны, решение может вызвать утечку памяти - person anstarovoyt; 15.01.2015
comment
Я бы подумал о голосовании против, потому что создание класса только для инициализации одного объекта кажется мне излишним. Но я недостаточно разбираюсь в java, чтобы знать, плохо ли это делать. Может быть, создание тысяч ненужных классов в большой программе считается хорошим кодированием на Java? Это также ужасно многословно, если в нем много элементов. Есть ли какие-либо преимущества у этого подхода по сравнению с другими предложенными ответами? - person ToolmakerSteve; 13.09.2015
comment
Возможно, он был отклонен, потому что он работает только для окончательных значений. Я согласен, что ваше решение действительно соответствует заданному вопросу, но вы знаете, что некоторые люди используют StackOverflow. - person Josh; 15.12.2015
comment
Вероятно, за него проголосовали против, потому что, по всей вероятности, большинство пользователей, которые будут использовать это решение, не прочитают / не поймут объяснение. Важно, чтобы каждый, кто этим пользуется, полностью понимал, что он делает и как это работает. - person forresthopkinsa; 14.08.2017
comment
Хотя это выглядит красиво, но это очень плохая идея, но это приведет к созданию ненужных объектов класса, которые необходимо будет немедленно удалить при сборке мусора. Наличие этого в вашем коде затрудняет диагностику будущих проблем с памятью только из-за небольшого синтаксического сахара. - person Justin Ohms; 15.11.2017
comment
Несмотря на то, что у такой инициализации есть известные недостатки, я бы поставил под сомнение ваше утверждение относительно. проблемы с памятью, особенно с учетом приведенных выше примечаний и представленного ограниченного сценария - person Brian Agnew; 15.11.2017
comment
Похоже, @BrianAgnew обсуждает это дополнительно в другом ответе SO. ???? - person Tommy Stanton; 23.12.2018

Вот самое близкое, что вы можете получить:

ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));

Вы можете пойти еще проще:

List<String> list = Arrays.asList("Ryan", "Julie", "Bob")

Если посмотреть на источник для Arrays.asList, он создает ArrayList, но по умолчанию приводится к List. Итак, вы могли бы сделать это (но не надежно для новых JDK):

ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
person Fred Haslam    schedule 03.05.2010
comment
ArrayList, созданный asList, не является java.util.ArrayList, только разделяет его. Фактически, этого не может быть, поскольку возвращаемое значение asList определено как список фиксированного размера, но ArrayList должен иметь переменный размер. - person meriton; 04.05.2010
comment
Я исправился. Я недостаточно углубился в источник. - person Fred Haslam; 04.05.2010

Что ж, в Java нет буквального синтаксиса для списков, поэтому вам нужно использовать .add ().

Если у вас много элементов, это немного многословно, но вы можете:

  1. используйте Groovy или что-то в этом роде
  2. использовать Arrays.asList (массив)

2 будет выглядеть примерно так:

String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));

Однако это приводит к созданию ненужных объектов.

person jayshao    schedule 03.05.2010

Выбранный ответ: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

Однако важно понимать, что выбранный ответ внутренне копирует элементы несколько раз перед созданием окончательного массива, и что есть способ уменьшить часть этой избыточности.

Начнем с понимания того, что происходит:

  1. Сначала элементы копируются в Arrays.ArrayList<T>, созданный статической фабрикой Arrays.asList(T...).

    Это не создает тот же класс, что и java.lang.ArrayList, несмотря на то, что имеет такое же простое имя класса. Он не реализует такие методы, как remove(int), несмотря на наличие интерфейса List. Если вы вызовете эти методы, он выдаст UnspportedMethodException. Но если все, что вам нужно, это список фиксированного размера, вы можете на этом остановиться.

  2. Затем Arrays.ArrayList<T>, созданный в # 1, передается конструктору ArrayList<>(Collection<T>), где вызывается метод collection.toArray() для его клонирования.

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. Затем конструктор решает, следует ли принять клонированный массив или снова скопировать его, чтобы удалить тип подкласса. Поскольку Arrays.asList(T...) внутренне использует массив типа T, тот самый, который мы передали в качестве параметра, конструктор всегда отклоняет использование клона, если T не является чистым объектом. (Например, String, Integer и т. Д. Все снова копируются, потому что они расширяют Object).

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    

Таким образом, наши данные были скопированы 3 раза просто для явной инициализации ArrayList. Мы могли бы уменьшить его до 2x, если мы заставим Arrays.AsList(T...) создать массив Object [], чтобы ArrayList мог позже принять его, что можно сделать следующим образом:

(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));

Или, может быть, просто добавление элементов после создания может быть наиболее эффективным.

person NameSpace    schedule 19.01.2016

Как насчет этого.

ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
person Ken de Guzman    schedule 05.06.2014

Вот как это делается с использованием свободного интерфейса библиотеки Java op4j (версия 1.1 была выпущена в декабре 2010 г.): -

List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();

Это очень классная библиотека, которая сэкономит вам массу времени.

person crsedgar    schedule 02.12.2011