Рубрики
Без рубрики

Инициализация списка Java в одной строке

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

Автор оригинала: baeldung.

1. Обзор

В этом кратком руководстве мы рассмотрим, как инициализировать Список с помощью однострочных строк.

Дальнейшее чтение:

Collections.emptyList() vs. Новый экземпляр Списка

Руководство по Java ArrayList

2. Создайте из массива

Мы можем создать Список из массива. И благодаря литералам массива мы можем инициализировать их в одной строке:

List list = Arrays.asList(new String[]{"foo", "bar"});

Мы можем доверять механизму varargs для обработки создания массива. С помощью этого мы можем написать более сжатый и читаемый код:

@Test
public void givenArraysAsList_thenInitialiseList() {
    List list = Arrays.asList("foo", "bar");

    assertTrue(list.contains("foo"));
}

Результирующий экземпляр этого кода реализует интерфейс List , но это не java.util.ArrayList или Связанный список . Вместо этого это Список , поддерживаемый исходным массивом, который имеет два значения, которые мы рассмотрим в остальной части этого раздела.

Хотя имя класса случайно ArrayList , оно находится в файле java.util.Массивы пакет.

2.1. Фиксированный Размер

Результирующий экземпляр из Arrays.asList будет иметь фиксированный размер:

@Test(expected = UnsupportedOperationException.class)
public void givenArraysAsList_whenAdd_thenUnsupportedException() {
    List list = Arrays.asList("foo", "bar");

    list.add("baz");
}

2.2. Общая ссылка

Исходный массив и список имеют одинаковые ссылки на объекты:

@Test
public void givenArraysAsList_whenCreated_thenShareReference(){
    String[] array = {"foo", "bar"};
    List list = Arrays.asList(array);
    array[0] = "baz";
 
    assertEquals("baz", list.get(0));
}

3. Создание из потока (Java 8)

Мы можем легко преобразовать Поток в любой вид Коллекции.

Поэтому с помощью заводских методов для Потоков мы можем создавать и инициализировать списки в одной строке:

@Test
public void givenStream_thenInitializeList(){
    List list = Stream.of("foo", "bar")
      .collect(Collectors.toList());
		
    assertTrue(list.contains("foo"));
}

Здесь следует отметить, что Коллекционеры.ToList() не гарантирует точную реализацию возвращенного Списка .

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

Некоторые источники подчеркивают, что Stream.of(…).collect(…) может иметь большую память и производительность, чем Arrays.asList() . Но почти во всех случаях это такая микрооптимизация, что разница невелика.

4. Заводские методы (Java 9)

JDK 9 представляет несколько удобных заводских методов для коллекций:

List list = List.of("foo", "bar", "baz");
Set set = Set.of("foo", "bar", "baz");

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

Эта тема более подробно рассматривается в этой статье .

5. Инициализация двойной скобки

В нескольких местах мы можем найти метод, называемый инициализацией двойных скобок, который выглядит следующим образом:

@Test
public void givenAnonymousInnerClass_thenInitialiseList() {
    List cities = new ArrayList() {{
        add("New York");
        add("Rio");
        add("Tokyo");
    }};

    assertTrue(cities.contains("New York"));
}

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

На самом деле в Java нет синтаксического элемента с двойными скобками; это два блока, отформатированных намеренно таким образом.

С помощью внешних фигурных скобок мы объявляем анонимный внутренний класс, который будет подклассом ArrayList . Мы можем объявить детали нашего подкласса внутри этих фигурных скобок.

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

Краткость этого синтаксиса заманчива. Тем не менее, это считается анти-паттерном.

Чтобы узнать больше об инициализации двойных скобок, ознакомьтесь с нашей статьей здесь .

6. Заключение

Современная Java предлагает несколько вариантов создания Коллекции в одной строке. Метод, который мы выбираем, почти полностью зависит от личных предпочтений, а не от технических рассуждений.

Важным выводом является то, что, хотя это выглядит изящно, анти-шаблон анонимной инициализации внутреннего класса (он же двойная скобка) имеет много негативных побочных эффектов.

Как всегда, код доступен на GitHub .