Инициализация ArrayList в одну строку

2370

Я хочу создать список параметров для тестирования. Сначала я сделал это:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

Затем я реорганизовал код следующим образом:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Есть ли лучший способ сделать это?

  • 30
    Если это предназначено для модульного тестирования, попробуйте Groovy для качелей. Вы можете написать свой тестовый код в нем во время тестирования кода Java и использовать ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]
  • 2
    В Java SE 7 вы можете заменить параметризованный тип конструктора пустым набором параметров типа (<>): Map <String, List <String >> myMap = new HashMap <> ();
Показать ещё 4 комментария
Теги:
arraylist
collections
initialization

32 ответа

1760
Лучший ответ

На самом деле, возможно, лучшим способом инициализации ArrayList является метод, который вы написали, так как ему не нужно создавать новый List любым способом:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

Ловушка заключается в том, что для обращения к этому экземпляру List требуется довольно много ввода.

Существуют альтернативы, такие как создание анонимного внутреннего класса с инициализатором экземпляра (также называемым "инициализацией двойной скобки" ):

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

Тем не менее, я не слишком люблю этот метод, потому что в итоге вы являетесь подклассом ArrayList, у которого есть инициализатор экземпляра, и этот класс создается только для создания одного объекта - это просто похоже на немного переборщить со мной.

Что было бы хорошо, если бы Предложение коллекции литералов для Project Монета была принята (предполагается, что она будет представлена ​​на Java 7, но она вряд ли будет частью Java 8.):

List<String> list = ["A", "B", "C"];

К сожалению, это вам не поможет, поскольку оно инициализирует неизменяемый List, а не ArrayList, и, кроме того, он пока недоступен, если он когда-либо будет.

  • 151
    См. Stackoverflow.com/questions/924285 для получения дополнительной информации об инициализации двойной скобки, за и против.
  • 5
    @ Эдди: хороший вызов для ссылки - одного предложения по инициализации в двойных скобках недостаточно, чтобы полностью описать его.
Показать ещё 6 комментариев
1778

Было бы проще, если бы вы просто объявили его как List - это должен быть ArrayList?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

Или, если у вас есть только один элемент:

List<String> places = Collections.singletonList("Buenos Aires");

Это означало бы, что places неизменный (при попытке изменить это вызовет исключение UnsupportedOperationException).

Чтобы создать изменяемый список, который является конкретным ArrayList, вы можете создать ArrayList из неизменяемого списка:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
  • 1
    Да, у моего класса есть приватный ArrayList <String>.
  • 16
    @Marcase: вы не можете изменить свой класс, чтобы использовать List вместо ArrayList?
Показать ещё 7 комментариев
710

Простой ответ

В Java 9 или более поздней версии:

List<String> strings = List.of("foo", "bar", "baz");

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


Java 8 или более ранняя версия:

List<String> strings = Arrays.asList("foo", "bar", "baz");

Это даст вам List поддерживаемый массивом, поэтому он не может изменить длину.
Но вы можете вызвать List.set, так что он все еще изменчив.


Короче ответ

Вы можете сделать Arrays.asList еще короче с помощью статического импорта:

List<String> strings = asList("foo", "bar", "baz");

Статический импорт:

import static java.util.Arrays.asList;  

Что любая современная IDE предложит и автоматически сделает для вас.
Например, в IntelliJ IDEA вы нажимаете Alt+Enter и выбираете Static import method...


Тем не менее, я не рекомендую List.of Java 9 List.of метод, потому что просто of за of становится путать.
List.of уже достаточно короткий и хорошо читается.


Использование Stream s

Почему это должен быть List?
В Java 8 или более поздней версии вы можете использовать более гибкий Stream:

Stream<String> strings = Stream.of("foo", "bar", "baz");

Вы можете объединить Stream s:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

Или вы можете перейти из Stream в List:

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

Но желательно просто использовать Stream не собирая его в List.


Если вам действительно нужен java.util.ArrayList

(Вы, вероятно, не.)
Процитирую JEP 269 (выделение мое):

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


Если вы хотите предварительно заполнить ArrayList и добавить к нему впоследствии (почему?), Используйте

List<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

или в Java 8 или ранее:

List<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

или используя Stream:

List<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

Но опять же, лучше просто использовать Stream напрямую, а не собирать его в List.


Программа для интерфейсов, а не для реализаций

Вы сказали, что объявили список как ArrayList в своем коде, но делать это следует только в том случае, если вы используете какой-либо элемент ArrayList, которого нет в List.

Что вы, скорее всего, не делаете.

Обычно вы должны просто объявлять переменные с помощью наиболее общего интерфейса, который вы собираетесь использовать (например, Iterable, Collection или List), и инициализировать их конкретной реализацией (например, ArrayList, LinkedList или Arrays.asList()).

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

Например:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList

// Java 10 makes this moot:
var strings = new ArrayList<String>();

Другим примером будет всегда объявлять переменную InputStream даже если это обычно FileInputStream или BufferedInputStream, потому что однажды вы или кто-то еще захотите использовать какой-либо другой тип InputStream.

  • 0
    Спасибо Вам большое. Я пытался пропустить «статический» импорт в моем коде, но компилятор не имел ничего из этого. Почему статический код необходим для работы кода?
  • 2
    @jollyroger: Arrays.asList является статическим методом. См. Docs.oracle.com/javase/1.5.0/docs/guide/language/…
Показать ещё 4 комментария
110

Если вам нужен простой список размером 1:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

Если вам нужен список из нескольких объектов:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
53

С Guava вы можете написать:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

В Гуаве есть и другие полезные статические конструкторы. Вы можете прочитать о них здесь.

Показать ещё 1 комментарий
31

Литералы коллекции не попали в Java 8, но можно использовать Stream API для инициализации списка в одной довольно длинной строке:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

Если вам нужно, чтобы ваш List был ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
25

В Java 9, как предложено в предложении по усовершенствованию JDK - 269, этого можно достичь, используя теперь литералы коллекций как -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

Также аналогичный подход будет применяться к Map -

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

что аналогично предложению Collection Literals, как заявлено @coobird. Также уточняется в документе JEP -


альтернативы

Языковые изменения были рассмотрены несколько раз и отклонены:

Проект монетного предложения, 29 марта 2009 г.

Проект монетного предложения, 30 марта 2009 г.

JEP 186 дискуссия по лямбда-деву, январь-март 2014

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

Related => В чем смысл перегруженных методов фабрики удобства для коллекций в Java 9

25
import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
  • 3
    Я не хочу добавлять новую зависимость просто для этого.
  • 5
    Это то же самое, что Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")) , который становится unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata")) с статический импорт. Вам не нужны Google Коллекции для этого.
Показать ещё 4 комментария
23

Вы можете создать фабричный метод:

public static ArrayList<String> createArrayList(String ... elements) {
  ArrayList<String> list = new ArrayList<String>();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

Но это не намного лучше, чем ваш первый рефакторинг.

Для большей гибкости он может быть общим:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}
  • 1
    Посмотрите на исходный пост, он запрашивает инициализацию массива в одну строку , а не 7 дополнительных строк.
  • 6
    @ LeoHolanda: Создание фабричных методов для каждой мелочи слишком много, я согласен. Но в зависимости от ситуации и от того, сколько раз будет использоваться этот метод, может иметь смысл создать его. Создание дополнительных слоев абстракции предназначено для устранения сложности путем создания более значимых методов, которые отражают намерения дизайнера.
15

В Java 9 мы можем легко инициализировать ArrayList в одну строку:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

или же

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Этот новый подход Java 9 имеет много преимуществ по сравнению с предыдущими:

  1. Космическая эффективность
  2. неизменность
  3. Поток Сейф

Смотрите этот пост для более подробной информации → В чем разница между List.of и Arrays.asList?

7

Вот еще один способ:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
7

С Коллекции Eclipse (ранее Коллекции GS), вы можете написать следующее:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

Вы также можете быть более конкретными в отношении типов и являются ли они взаимозаменяемыми или неизменяемыми.

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Вы также можете сделать то же самое с Sets and Bags:

Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Примечание: Я являюсь коммиттером для коллекций Eclipse.

7

О самом компактном способе сделать это:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
7

Просто используйте приведенный ниже код следующим образом.

List<String> list = new ArrayList<String>() {{
            add("A");
            add("B");
            add("C");
}};
  • 2
    @bsd Вы можете использовать этот метод для объявления списка перед вводом любого метода. Таким образом, при определении переменных класса содержимое может быть добавлено в список без необходимости вызова метода для этого.
  • 1
    инициализации двойных скобок следует избегать, насколько это возможно. см .: stackoverflow.com/a/924326/760393
6

Вы можете использовать приведенные ниже инструкции:

Фрагмент кода:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);
  • 0
    Вы можете встроить первое выражение, чтобы иметь компактное решение: letters = Arrays.asList(new String[]{"A", "B", "C"});
6

(Должен быть комментарий, но слишком длинный, поэтому новый ответ). Как уже упоминалось, метод Arrays.asList имеет фиксированный размер, но это не единственная проблема с ним. Он также не очень хорошо обрабатывает наследование. Например, предположим, у вас есть следующее:

class A{}
class B extends A{}

public List<A> getAList(){
    return Arrays.asList(new B());
}

Вышеуказанное приводит к ошибке компилятора, потому что List<B> (то, что возвращает Arrays.asList) не является подклассом List<A>, даже если вы можете добавить объекты типа B в объект List<A>, Чтобы обойти это, вам нужно сделать что-то вроде:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

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

5

Java 9 имеет следующий способ создания неизменяемого списка:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

который легко адаптируется для создания изменяемого списка, если требуется:

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Аналогичные методы доступны для Set и Map.

5

Как Том сказал:

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

Но поскольку вы жаловались на желание ArrayList, вы должны сначала знать, что ArrayList является подклассом List, и вы можете просто добавить эту строку:

ArrayList<String> myPlaces = new ArrayList(places);

Хотя, это может заставить вас жаловаться на "производительность".

В этом случае для меня это не имеет смысла, почему, поскольку ваш список предопределен, он не был определен как массив (поскольку размер известен во время инициализации). И если это вариант для вас:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

Если вы не заботитесь о незначительных различиях в производительности, вы можете просто скопировать массив в ArrayList очень просто:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

Хорошо, но в будущем вам нужно немного больше, чем просто название места, вам нужен код страны. Предполагая, что это все еще предопределенный список, который никогда не изменится во время выполнения, тогда он подходит для использования набора enum, который потребует повторной компиляции, если список необходимо изменить в будущем.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

станет:

enum Places {
    BUENOS_AIRES("Buenos Aires",123),
    CORDOBA("Córdoba",456),
    LA_PLATA("La Plata",789);

    String name;
    int code;
    Places(String name, int code) {
      this.name=name;
      this.code=code;
    }
}

Enum имеет статический метод values, который возвращает массив, содержащий все значения перечисления в том порядке, в котором они объявлены, например:

for (Places p:Places.values()) {
    System.out.printf("The place %s has code %d%n",
                  p.name, p.code);
}

В этом случае, я думаю, вам не понадобится ваш ArrayList.

P.S. Randyaa продемонстрировал еще один хороший способ, используя статический метод утилиты Collections.addAll.

4

Вы можете использовать StickyList из Cactoos:

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);
4
List<String> names = Arrays.asList("2","@2234","21","11");
3

Да с помощью массивов вы можете инициализировать список массивов в одной строке,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
3

Попробуйте использовать эту строку кода:

Collections.singletonList(provider)
  • 1
    Добавьте краткое описание вашего ответа.
2

В Java вы не можете делать

ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Как указывалось, вам нужно выполнить инициализацию с двойной привязкой:

List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};

Но это может заставить вас добавить аннотацию @SuppressWarnings("serial") или создать серийный UUID, который раздражает. Также большинство форматировщиков кода разворачивают это на несколько операторов/строк.

В качестве альтернативы вы можете сделать

List<String> places = Arrays.asList(new String[] {"x", "y" });

но тогда вы можете сделать @SuppressWarnings("unchecked").

Также, согласно javadoc, вы должны это сделать:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

Но я не могу его скомпилировать с JDK 1.6.

  • 5
    Неправильно! Вы можете сделать первую строку, и это правильный ответ, кстати
1

Иногда я просто чувствую, что люди просто должны использовать Groovy и пусть Java остается в покое. Хорошо, что он работает на JVM, поэтому вы можете скопировать чистый Java-код в любом месте в файле Groovy, и он будет работать.

О объявлении списка в одной строке, вот как он выглядит в Groovy:

def list1 = [1,2,3]

Что это, maan!!!

Ниже приведен список Groovy.

Дополнительно

Объявление карты в Groovy в одной строке:

def map1 = [key1:1,key2:2]

Подробнее о Groovy maps.

Чтение файла JSON,

{ "map1":{"map2":{"key":"value1"}}}

в одной строке:

String value = new JsonSlurper().parse("path\\to\\file")["map1"]["map2"]["key"]

или

String value = new JsonSlurper().parse("path\\to\\file").map1.map2.key

Оба набора value - value1.

Представьте, что вы делаете то же самое с Jackson API. Вы должны написать соответствующие POJOs для map1 и map2. Затем скомпилируйте. Также каждый раз, когда JSON изменяется, вы должны отражать эти изменения в POJO. Это полностью поражает цель создания функциональности JSON. Это смертельная цепочка перекомпиляции кода-кода. Не просто настроить и уйти.

Я плачу, когда меня попросили использовать Java. Почему мир почему???? (или, пожалуйста, просветите меня, если я ошибаюсь... уменьшит большую часть моей боли в Java World)

1

Вот код от AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

Декларация: я разработчик AbacusUtil.

1

Лучший способ сделать это:

package main_package;

import java.util.ArrayList;


public class Stackkkk {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        add(list, "1", "2", "3", "4", "5", "6");
        System.out.println("I added " + list.size() + " element in one line");
    }

    public static void add(ArrayList<Object> list,Object...objects){
        for(Object object:objects)
            list.add(object);
    }
}

Просто создайте функцию, которая может иметь столько элементов, сколько вы хотите, и вызовите ее, чтобы добавить их в одну строку.

  • 1
    Если вы пройдете через все проблемы, вы можете также сделать это методом шаблона вместо использования простого Object .
1
Collections.singletonList(messageBody)

Если вам нужно будет иметь список одного элемента!

Коллекции из пакета java.util.

0

Почему бы не сделать простую служебную функцию, которая делает это?

static <A> ArrayList<A> ll(A... a) {
  ArrayList l = new ArrayList(a.length);
  for (A x : a) l.add(x);
  return l;
}

" ll " означает "буквальный список".

ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
0

Для меня Arrays.asList() - лучший и удобный. Мне всегда нравится инициализировать этот путь. Если вы новичок в сборниках Java, я хотел бы, чтобы вы ссылались на ArrayList инициализацию

  • 0
    Почему Arrays.asList () лучше, чем создание нового ArrayList в одну строку с помощью методов add() ?
-2

Собственно, это можно сделать в одной строке:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
  • 3
    Могу я спросить, что это добавляет к вопросу? Этот ответ уже покрыт несколько раз другими ответами.
  • 2
    Этот ответ не добавляет много к уже существующим.
Показать ещё 1 комментарий
-3
public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
}

Это реализация Arrays.asList, поэтому вы можете пойти с

ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");
-5

В среде Apple WebObjects Foundation вы можете сделать это.

NSArray<String> places1 = new NSArray<String>("Buenos Aires", "Córdoba", "La Plata");
NSMutableArray<String> places2 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");
List<String> places3 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");

Основа WebObjects Foundation была перенесена с Objective-C на Java более десяти лет назад и была обновлена ​​после добавления поддержки Java для генериков... Интересно, почему что-то подобное не было реализовано в классах Java Collections.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню