Какой лучший способ инициализировать ArrayList в одной строке в Java?
Я пытаюсь создать список опций для тестовых целей. Сначала я использовал этот подход:
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"));
Существует ли более эффективный или более чистый способ инициализации ArrayList с несколькими элементами в одной строке кода Java?
Лучший способ инициализации ArrayList в одну строку зависит от вашей версии Java и необходимости создания изменяемого или неизменяемого списка. В большинстве случаев, включая сценарии тестирования, следует использовать new ArrayList<>(Arrays.asList(...)) для Java 8 и более ранних версий, или new ArrayList<>(List.of(...)) для Java 9+.
Содержание
- Традиционный подход с Arrays.asList()
- Современный метод List.of() (Java 9+)
- Подход с использованием Stream API (Java 8+)
- Инициализация с двойными фигурными скобками
- Сравнение методов
- Рекомендации для тестирования
- Рассмотрения производительности
Традиционный подход с Arrays.asList()
Метод Arrays.asList() доступен с Java 1.2 и является наиболее распространенным подходом для инициализации списка с несколькими элементами. Однако важно понимать его ограничения.
// Это создает список фиксированного размера, который нельзя изменять
List<String> places = Arrays.asList("Буэнос-Айрес", "Кордова", "Ла-Плата");
// Чтобы получить изменяемый ArrayList, оберните его:
ArrayList<String> mutablePlaces = new ArrayList<>(Arrays.asList("Буэнос-Айрес", "Кордова", "Ла-Плата"));
Ключевые характеристики:
- Возвращает интерфейс
List, а не реализациюArrayListилиLinkedList - Создает список фиксированного размера, не позволяющий добавлять или удалять элементы
- Список поддерживается исходным массивом, поэтому изменения элементов массива отражаются в списке
- Доступен во всех версиях Java
Как объясняется на Stack Overflow, “Arrays.asList() возвращает java.util.List, а не ArrayList или LinkedList. Еще один заслуживающий внимания момент заключается в том, что список, возвращаемый Arrays.asList(), имеет фиксированную длину и не позволяет добавлять или удалять элементы из него.”
Современный метод List.of() (Java 9+)
Java 9 представила List.of() как более удобную и безопасную альтернативу Arrays.asList() для создания неизменяемых списков.
// Создает неизменяемый список
List<String> immutablePlaces = List.of("Буэнос-Айрес", "Кордова", "Ла-Плата");
// Чтобы получить изменяемый ArrayList, оберните его:
ArrayList<String> mutablePlaces = new ArrayList<>(List.of("Буэнос-Айрес", "Кордова", "Ла-Плата"));
Ключевые характеристики:
- Возвращает неизменяемый список (нельзя изменить после создания)
- Поддерживает значения null (в отличие от Set.of() и Map.of())
- Более эффективен по памяти, чем Arrays.asList()
- Более чистый синтаксис и безопасность типов
- Доступен с Java 9+
Как отмечает Baeldung, “В отличие от Arrays.asList(), Java 9 представила более удобный метод, List.of()”
Подход с использованием Stream API (Java 8+)
Java 8 и более поздние версии поддерживают использование Stream API для создания списков, что может быть полезно в более сложных сценариях инициализации.
// Использование Stream.of() с toList() (Java 16+)
List<String> places = Stream.of("Буэнос-Айрес", "Кордова", "Ла-Плата").toList();
// Использование collect() (Java 8+)
List<String> places = Stream.of("Буэнос-Айрес", "Кордова", "Ла-Плата")
.collect(Collectors.toList());
// Для получения именно ArrayList
ArrayList<String> places = Stream.of("Буэнос-Айрес", "Кордова", "Ла-Плата")
.collect(Collectors.toCollection(ArrayList::new));
Ключевые характеристики:
- Гибкость для сложной логики инициализации
- Доступен с Java 8+
- Java 16+ предоставляет упрощенный метод
toList() - Более многословный, чем другие подходы для простых случаев
Инициализация с двойными фигурными скобками
Этот подход использует анонимный внутренний класс с инициализатором экземпляра, хотя в целом считается анти-паттерном.
ArrayList<String> places = new ArrayList<String>() {{
add("Буэнос-Айрес");
add("Кордова");
add("Ла-Плата");
}};
Ключевые характеристики:
- Создает ненужный анонимный внутренний класс
- Может вызывать утечки памяти из-за скрытой ссылки
- Считается анти-паттерном большинством экспертов Java
- Не рекомендуется для производственного кода
Как отмечает Academic Help, “инициализация с двойными фигурными скобками считается анти-паттерном и должна использоваться с осторожностью.”
Сравнение методов
| Метод | Версия Java | Изменяемость | Поддержка null | Производительность | Лучше всего подходит |
|---|---|---|---|---|---|
Arrays.asList() |
Все | Фиксированный размер | Да | Хорошая | Обратная совместимость |
List.of() |
9+ | Неизменяемый | Да | Отличная | Современный Java, неизменяемые списки |
Stream.of().toList() |
16+ | Неизменяемый | Да | Хорошая | Сложная инициализация |
Stream.of().collect() |
8+ | Изменяемый | Да | Хорошая | Сложная изменяемая инициализация |
| Двойные фигурные скобки | Все | Изменяемый | Да | Плохая | Устаревший код (избегать) |
Рекомендации для тестирования
Для вашего сценария тестирования, вот лучшие подходы в зависимости от версии Java:
Java 8 и более ранние версии:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Буэнос-Айрес", "Кордова", "Ла-Плата"));
Java 9 и более поздние версии:
ArrayList<String> places = new ArrayList<>(List.of("Буэнос-Айрес", "Кордова", "Ла-Плата"));
Для неизменяемых тестовых данных:
List<String> places = List.of("Буэнос-Айрес", "Кордова", "Ла-Плата");
Как объясняет BeginnersBook, “В Java 9 и более поздних версиях вы можете использовать List.of() для создания неизменяемого списка, а затем передать его в конструктор ArrayList, если вам нужен изменяемый список.”
Рассмотрения производительности
Для целей тестирования различия в производительности обычно незначительны, но вот общие рекомендации:
List.of()обычно наиболее эффективен для неизменяемых списковArrays.asList()имеет хорошую производительность, но создает списки фиксированного размера- Подходы с использованием Stream имеют немного больше издержек из-за конвейера потока
- Инициализация с двойными фигурными скобками имеет худшую производительность из-за создания анонимного класса
Как демонстрирует Baeldung, “Исходный массив и список совместно используют те же ссылки на объекты” при использовании Arrays.asList(), что может быть как преимуществом, так и соображением для тестирования.
Заключение
Для инициализации ArrayList с несколькими элементами в одну строку:
- Если вы используете Java 9+: Используйте
new ArrayList<>(List.of(...))для самого чистого, эффективного изменяемого ArrayList - Если вы используете Java 8 или более ранние версии: Используйте
new ArrayList<>(Arrays.asList(...))для обратной совместимости - Для неизменяемых тестовых данных: Используйте
List.of(...)напрямую, если вам не нужно изменять список - Избегайте: Инициализации с двойными фигурными скобками из-за ее статуса анти-паттерна
Ваш текущий рефакторинговый подход с использованием Arrays.asList() вполне подходит для Java 8 и более ранних версий, и вы должны рассмотреть возможность перехода на List.of() при обновлении до Java 9+ для лучшей безопасности типов и производительности.
Источники
- Stack Overflow - Инициализация ArrayList в одну строку
- Baeldung - Инициализация Java List в одну строку
- Baeldung - Различие между Arrays.asList() и List.of()
- BeginnersBook - Как инициализировать ArrayList в Java
- Academic Help - Как инициализировать список в Java
- CodeJava - Инициализация ArrayList со значениями в одну строку в Java
- Java2Blog - Инициализация ArrayList со значениями в Java