1. Обзор
В этом кратком руководстве мы рассмотрим, как инициализировать Список с помощью однострочных строк.
Дальнейшее чтение:
Collections.emptyList() vs. Новый экземпляр Списка
Руководство по Java ArrayList
2. Создайте из массива
Мы можем создать Список из массива. И благодаря литералам массива мы можем инициализировать их в одной строке:
Listlist = Arrays.asList(new String[]{"foo", "bar"});
Мы можем доверять механизму varargs для обработки создания массива. С помощью этого мы можем написать более сжатый и читаемый код:
@Test public void givenArraysAsList_thenInitialiseList() { Listlist = 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() { Listlist = Arrays.asList("foo", "bar"); list.add("baz"); }
2.2. Общая ссылка
Исходный массив и список имеют одинаковые ссылки на объекты:
@Test public void givenArraysAsList_whenCreated_thenShareReference(){ String[] array = {"foo", "bar"}; Listlist = Arrays.asList(array); array[0] = "baz"; assertEquals("baz", list.get(0)); }
3. Создание из потока (Java 8)
Мы можем легко преобразовать Поток в любой вид Коллекции.
Поэтому с помощью заводских методов для Потоков мы можем создавать и инициализировать списки в одной строке:
@Test public void givenStream_thenInitializeList(){ Listlist = Stream.of("foo", "bar") .collect(Collectors.toList()); assertTrue(list.contains("foo")); }
Здесь следует отметить, что Коллекционеры.ToList() не гарантирует точную реализацию возвращенного Списка .
Нет никакого общего контракта о изменчивости, сериализуемости или потокобезопасности возвращаемого экземпляра. Таким образом, наш код не должен полагаться ни на одно из этих свойств.
Некоторые источники подчеркивают, что Stream.of(…).collect(…) может иметь большую память и производительность, чем Arrays.asList() . Но почти во всех случаях это такая микрооптимизация, что разница невелика.
4. Заводские методы (Java 9)
JDK 9 представляет несколько удобных заводских методов для коллекций:
Listlist = List.of("foo", "bar", "baz"); Set set = Set.of("foo", "bar", "baz");
Одна важная деталь заключается в том, что возвращаемые экземпляры являются неизменяемыми. Кроме того, заводские методы имеют ряд преимуществ в плане экономичности пространства и безопасности резьбы.
Эта тема более подробно рассматривается в этой статье .
5. Инициализация двойной скобки
В нескольких местах мы можем найти метод, называемый инициализацией двойных скобок, который выглядит следующим образом:
@Test public void givenAnonymousInnerClass_thenInitialiseList() { Listcities = new ArrayList() {{ add("New York"); add("Rio"); add("Tokyo"); }}; assertTrue(cities.contains("New York")); }
Название “инициализация двойной скобки” вводит в заблуждение. Хотя синтаксис может выглядеть компактным и элегантным, он опасно скрывает то, что происходит под капотом.
На самом деле в Java нет синтаксического элемента с двойными скобками; это два блока, отформатированных намеренно таким образом.
С помощью внешних фигурных скобок мы объявляем анонимный внутренний класс, который будет подклассом ArrayList . Мы можем объявить детали нашего подкласса внутри этих фигурных скобок.
Как обычно, мы можем использовать блоки инициализатора экземпляра, и именно отсюда берется внутренняя пара фигурных скобок.
Краткость этого синтаксиса заманчива. Тем не менее, это считается анти-паттерном.
Чтобы узнать больше об инициализации двойных скобок, ознакомьтесь с нашей статьей здесь .
6. Заключение
Современная Java предлагает несколько вариантов создания Коллекции в одной строке. Метод, который мы выбираем, почти полностью зависит от личных предпочтений, а не от технических рассуждений.
Важным выводом является то, что, хотя это выглядит изящно, анти-шаблон анонимной инициализации внутреннего класса (он же двойная скобка) имеет много негативных побочных эффектов.
Как всегда, код доступен на GitHub .