Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Виды List в Java
List — это интерфейс коллекции из пакета java.util, который представляет упорядоченное собрание элементов, в котором разрешены дубликаты. Java предоставляет множество реализаций List, каждая со своими характеристиками и применением.
1. ArrayList
ArrayList — наиболее распространённая реализация List, основанная на динамическом массиве. Обеспечивает быстрый доступ по индексу.
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
fruits.add("Apple"); // Дубликаты разрешены
System.out.println(fruits); // [Apple, Banana, Cherry, Apple]
System.out.println("Size: " + fruits.size()); // 4
System.out.println("Get at index 1: " + fruits.get(1)); // Banana
System.out.println("Index of Apple: " + fruits.indexOf("Apple")); // 0
// Итерация
for (String fruit : fruits) {
System.out.println(fruit);
}
// Удаление
fruits.remove(0); // Удалить по индексу
fruits.remove("Banana"); // Удалить по значению
System.out.println(fruits); // [Cherry, Apple]
}
}
Характеристики:
- Доступ по индексу: O(1)
- Добавление/удаление в конец: O(1)
- Добавление/удаление в середину: O(n)
- Не потокобезопасна
- Допускает null элементы
- Размер растёт динамически
2. LinkedList
LinkedList — реализация List на основе двусвязного списка. Хорошо для частого добавления/удаления в начале или конце.
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<String> fruits = new LinkedList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println(fruits); // [Apple, Banana, Cherry]
// Операции в начале и конце (очень быстрые)
fruits.addFirst("Grape"); // Добавить в начало
fruits.addLast("Orange"); // Добавить в конец
System.out.println("First: " + fruits.getFirst()); // Grape
System.out.println("Last: " + fruits.getLast()); // Orange
fruits.removeFirst(); // Удалить первый
fruits.removeLast(); // Удалить последний
System.out.println(fruits); // [Apple, Banana, Cherry]
// LinkedList можно использовать как Queue
fruits.offer("Lemon"); // Добавить в очередь
String polled = fruits.poll(); // Получить и удалить первый
System.out.println("Polled: " + polled); // Apple
}
}
Характеристики:
- Доступ по индексу: O(n)
- Добавление/удаление в начало или конец: O(1)
- Добавление/удаление в середину: O(n) для поиска + O(1) для вставки
- Не потокобезопасна
- Допускает null элементы
- Реализует Queue и Deque интерфейсы
3. Vector
Vector — старая реализация List, эквивалент ArrayList из Java 1.0. Потокобезопасна, но устаревшая.
import java.util.Vector;
import java.util.List;
public class VectorExample {
public static void main(String[] args) {
List<String> fruits = new Vector<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println(fruits);
System.out.println("Size: " + fruits.size());
System.out.println("Capacity: " + ((Vector) fruits).capacity());
}
}
Характеристики:
- Потокобезопасна (синхронизирована)
- Производительность хуже ArrayList (синхронизация имеет цену)
- УСТАРЕВШАЯ — используйте Collections.synchronizedList() или CopyOnWriteArrayList
- Удваивает размер при переполнении
4. CopyOnWriteArrayList
CopyOnWriteArrayList — потокобезопасная реализация List для многопоточных приложений. При каждой модификации создаётся копия массива.
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.List;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
List<String> fruits = new CopyOnWriteArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
// Потокобезопасно для многопоточных операций
fruits.add("Orange");
fruits.remove(0);
// Итерация не требует синхронизации
for (String fruit : fruits) {
System.out.println(fruit);
}
// Многопоточный пример
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
fruits.add("Fruit" + i);
}
});
Thread t2 = new Thread(() -> {
for (String fruit : fruits) {
System.out.println(fruit);
}
});
t1.start();
t2.start();
}
}
Характеристики:
- Потокобезопасна
- Хорошо для чтения, плохо для записи (копирование массива при каждой модификации)
- Итерация не требует синхронизации
- Допускает null элементы
5. Collections.unmodifiableList (неизменяемый список)
unmodifiableList — создание неизменяемой (read-only) версии List.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UnmodifiableListExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
// Создание неизменяемого списка
List<String> immutableFruits = Collections.unmodifiableList(fruits);
System.out.println(immutableFruits); // [Apple, Banana, Cherry]
// immutableFruits.add("Orange"); // UnsupportedOperationException
// Изменение исходного списка влияет на неизменяемый
fruits.add("Orange");
System.out.println(immutableFruits); // [Apple, Banana, Cherry, Orange]
}
}
6. Collections.synchronizedList (синхронизированный список)
synchronizedList — получение потокобезопасной обёртки для обычного List.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> unsafeList = new ArrayList<>();
List<String> safeList = Collections.synchronizedList(unsafeList);
safeList.add("Apple");
safeList.add("Banana");
// Потокобезопасно
new Thread(() -> {
for (int i = 0; i < 100; i++) {
safeList.add("Fruit" + i);
}
}).start();
}
}
7. Collections.singletonList и Collections.emptyList
import java.util.Collections;
import java.util.List;
public class SpecialListExample {
public static void main(String[] args) {
// Список с одним элементом
List<String> single = Collections.singletonList("Apple");
System.out.println(single); // [Apple]
// single.add("Banana"); // UnsupportedOperationException
// Пустой список
List<String> empty = Collections.emptyList();
System.out.println(empty); // []
// empty.add("Apple"); // UnsupportedOperationException
}
}
8. Arrays.asList
asList — преобразование массива в List (фиксированного размера).
import java.util.Arrays;
import java.util.List;
public class ArraysAsListExample {
public static void main(String[] args) {
String[] array = {"Apple", "Banana", "Cherry"};
// Список фиксированного размера
List<String> list = Arrays.asList(array);
System.out.println(list); // [Apple, Banana, Cherry]
// Можно изменять элементы
list.set(0, "Orange");
System.out.println(array[0]); // Orange (изменение отражается на массиве)
// Но нельзя добавлять/удалять
// list.add("Lemon"); // UnsupportedOperationException
// Для полноценного List нужно создать новый ArrayList
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
mutableList.add("Lemon"); // OK
}
}
Таблица сравнения
| List | Доступ | Вставка конец | Вставка начало | Удаление | Потокобезопасна | Null |
|---|---|---|---|---|---|---|
| ArrayList | O(1) | O(1) | O(n) | O(n) | Нет | Да |
| LinkedList | O(n) | O(1) | O(1) | O(1) | Нет | Да |
| Vector | O(1) | O(1) | O(n) | O(n) | Да | Да |
| CopyOnWriteArrayList | O(1) | O(n) | O(n) | O(n) | Да | Да |
| synchronizedList | Зависит | Зависит | Зависит | Зависит | Да | Зависит |
Рекомендации по использованию
- ArrayList — стандартный выбор для большинства случаев
- LinkedList — когда часто добавляем/удаляем в начало или используем как Queue
- Vector — НИКОГДА не используйте (устаревший класс)
- CopyOnWriteArrayList — для многопоточных приложений с частым чтением
- Collections.synchronizedList() — для обёртки существующего List
- Collections.unmodifiableList() — для защиты от случайных изменений
- Arrays.asList() — для быстрого преобразования массива, но помните про фиксированный размер