← Назад к вопросам

Какие знаешь виды List?

2.0 Middle🔥 161 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Виды 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
ArrayListO(1)O(1)O(n)O(n)НетДа
LinkedListO(n)O(1)O(1)O(1)НетДа
VectorO(1)O(1)O(n)O(n)ДаДа
CopyOnWriteArrayListO(1)O(n)O(n)O(n)ДаДа
synchronizedListЗависитЗависитЗависитЗависитДаЗависит

Рекомендации по использованию

  • ArrayList — стандартный выбор для большинства случаев
  • LinkedList — когда часто добавляем/удаляем в начало или используем как Queue
  • Vector — НИКОГДА не используйте (устаревший класс)
  • CopyOnWriteArrayList — для многопоточных приложений с частым чтением
  • Collections.synchronizedList() — для обёртки существующего List
  • Collections.unmodifiableList() — для защиты от случайных изменений
  • Arrays.asList() — для быстрого преобразования массива, но помните про фиксированный размер