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

java collections arraylist initialization


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

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"));

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




Answer 1 coobird


На самом деле, вероятно, «лучший» способ инициализации 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 Coin было принято (оно должно было быть представлено в Java 7, но вряд ли оно будет частью Java 8).

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

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




Answer 2 Tom


Было бы проще, если бы вы просто объявили его как 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"));



Answer 3 Christoffer Hammarström


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

В Java 9 или более поздней List.of() после добавления List.of () :

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

В Java 10 или более поздней версии это можно сократить с помощью ключевого слова var .

var 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 метод List.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 :

import static java.util.stream.Collectors.toList;

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

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


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

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

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


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

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

или на Яве 8 или более ранней:

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

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

import static java.util.stream.Collectors.toCollection;

ArrayList<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() ).

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

Например, если вы передаете ArrayList в void method(...) :

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

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




Answer 4 Randyaa


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

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

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

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



Answer 5 Paweł Adamski


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

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

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