1. Введение
Когда-то мы с вами уже разбирались с «бесконечными массивами» — списками. Давайте углубим наши знания, а для этого ещё раз зададимся вопросом, что такое «классический» массив. Если приглядеться, он напоминает коробку для инструментов с фиксированным количеством отделений. Допустим, в коробке есть 10 ячеек. У вас появился 11-й инструмент, что теперь? Придётся покупать новую коробку! Вот и традиционный массив имеет фиксированный размер, и после создания его длина, уж какая есть, не изменится.
Если нужно добавить или удалить элемент, приходится создавать новый массив и копировать данные вручную. В массиве легко и быстро можно найти элемент по индексу, а вот вставить элемент в середину массива — это не просто «вставить», а «сдвинуть всё вправо», а при удалении — «сдвинуть всё влево». Это медленно и неудобно. Кроме того, массив не хранит в себе никакой дополнительной «логики»: он просто держит набор ячеек, а уже сортировку, поиск по содержимому или проверку уникальности приходится делать внешними средствами.
Пример: динамический список студентов
Допустим, вы пишете приложение для учёта студентов в группе. Сначала в группе 5 человек, потом пришёл ещё один, потом кто-то ушёл. С массивом это выглядело бы так:
String[] students = new String[5];
students[0] = "Иван";
students[1] = "Мария";
// и так далее...
// Ой, пришёл ещё один студент
// Нужно создавать новый массив!
String[] newStudents = new String[6];
for (int i = 0; i < students.length; i++) {
newStudents[i] = students[i];
}
newStudents[5] = "Алексей";
students = newStudents;
Удобно? Мягко говоря, нет. А если таких операций много? Тут уже хочется что-то поудобнее...
2. Что такое коллекция?
Коллекция — это объект, который служит контейнером для хранения группы других объектов (элементов). Коллекции позволяют добавлять, удалять, перебирать элементы, а также выполнять другие операции: поиск, сортировку, фильтрацию и т.д.
В Java все коллекции реализуют или наследуют от интерфейса Collection (или, для отображений — от Map). Коллекция — это не просто «куча чего-то», а структура, которая предоставляет удобный, продуманный набор методов для работы с элементами.
Почему коллекции — это объекты?
Потому что коллекции реализованы как классы, а значит, вы можете создавать коллекции любых объектов, комбинировать их, наследовать, расширять, использовать в своих классах и методах.
Пример:
import java.util.ArrayList;
import java.util.List;
List<String> students = new ArrayList<>();
students.add("Иван");
students.add("Мария");
students.add("Алексей");
Вуаля! Теперь можно добавлять сколько угодно студентов, не заботясь о размере массива.
3. Типичные задачи, которые решают коллекции
Коллекции — это швейцарский нож для работы с данными. Вот какие задачи они позволяют решать:
- Хранение динамического списка данных: Например, список студентов, задачи в планировщике, сообщения в чате.
- Поиск и фильтрация: Быстро найти элемент, проверить его наличие, получить все элементы, удовлетворяющие какому-то условию.
- Сортировка: Легко отсортировать элементы по нужному критерию.
- Удаление и добавление элементов: Вставка и удаление элементов в любом месте коллекции без необходимости вручную копировать массивы.
- Группировка по ключу: Например, телефонная книга, где каждому имени соответствует номер телефона.
- Гарантия уникальности: Например, множество всех уникальных слов в тексте.
Пример: телефонная книга
С массивом:
- Как найти номер по имени? Придётся перебирать массив и сравнивать имена.
- Как добавить новую пару? Придётся расширять массив.
- Как гарантировать, что имена не повторяются? Ещё сложнее.
С коллекцией:
- Используем Map<String, String> — и всё работает «из коробки».
4. Обзор основных видов коллекций
В Java коллекции делятся на три основные группы:
| Вид коллекции | Интерфейс/Класс | Для чего используется |
|---|---|---|
| Список | List, ArrayList | Упорядоченный набор элементов, допускает дублирование, доступ по индексу |
| Множество | Set, HashSet | Хранит только уникальные элементы, порядок не гарантируется |
| Отображение | Map, HashMap | Хранит пары ключ-значение, быстрый поиск по ключу |
Списки (List)
- Упорядоченные коллекции, допускают дубликаты.
- Можно получить элемент по индексу.
- Примеры: ArrayList, LinkedList.
Множества (Set)
- Хранят только уникальные элементы.
- Нет доступа по индексу.
- Примеры: HashSet, TreeSet.
Отображения (Map)
- Хранят пары ключ-значение.
- Быстрый поиск по ключу.
- Примеры: HashMap, TreeMap.
Визуальная схема (очень условная):
+------------------+ +-------------------+ +---------------------+
| List | | Set | | Map |
|------------------| |-------------------| |---------------------|
| [a, b, c, d, a] | | {a, b, c, d} | | {a=1, b=2, c=3} |
| Индексация: есть | | Индексация: нет | | Поиск по ключу |
| Дубликаты: да | | Дубликаты: нет | | Ключи уникальны |
+------------------+ +-------------------+ +---------------------+
5. Полезные нюансы
Когда использовать какую коллекцию?
List — когда важен порядок элементов, нужны дубликаты, нужен доступ по индексу (например, список задач, история сообщений).
Set — когда нужны только уникальные элементы, порядок не важен (например, множество уникальных пользователей).
Map — когда нужно сопоставлять ключи и значения (например, телефонная книга, где имя — ключ, телефон — значение).
Аналогии из жизни
List — очередь в столовой: первый пришёл — первый обслужен, можно встать в очередь несколько раз (дубликаты).
Set — список гостей на вечеринке: каждый гость только один раз (уникальность).
Map — адресная книга: у каждого имени есть свой телефон.
Краткая шпаргалка: коллекции vs массивы
| Массив (int[]) | Коллекция (List<Integer>) | |
|---|---|---|
| Размер | Фиксированный | Динамический |
| Добавление элемента | Неудобное | Легко: add() |
| Удаление элемента | Неудобное | Легко: remove() |
| Поиск по значению | Ручной перебор | Методы: contains(), и др. |
| Сортировка | Через Arrays.sort() | Через Collections.sort(), методы коллекций |
| Поддержка уникальности | Нет | Через Set |
| Пары ключ-значение | Нет | Через Map |
6. Связь коллекций с ООП
Коллекции — это объекты, реализующие определённые интерфейсы (List, Set, Map). Это значит, что вы можете:
- Хранить в коллекциях любые объекты, в том числе экземпляры ваших собственных классов.
- Создавать коллекции коллекций (например, список списков).
- Использовать коллекции как параметры и возвращаемые значения методов.
- Расширять функциональность коллекций с помощью наследования и композиции.
Пример: коллекция объектов вашего класса
import java.util.ArrayList;
import java.util.List;
class Student {
String name;
int age;
// Конструктор, геттеры/сеттеры и т.д.
}
public class Main {
public static void main(String[] args) {
List<Student> group = new ArrayList<>();
group.add(new Student("Иван", 20));
group.add(new Student("Мария", 21));
// и так далее...
}
}
7. Типичные ошибки при работе с коллекциями
Ошибка №1: Использование коллекций без типа (raw types).
Если вы пишете ArrayList list = new ArrayList(), то при добавлении любого объекта (например, строки и числа вперемешку) компилятор не будет ругаться, но потом при попытке достать элемент и привести его к нужному типу можно получить ошибку времени выполнения (ClassCastException). Всегда используйте дженерики: ArrayList<String> list = new ArrayList<>().
Ошибка №2: Забыли импортировать нужный класс.
Если вы видите ошибку «cannot find symbol», проверьте, что в начале файла есть строка import java.util.ArrayList; или нужный импорт для вашей коллекции.
Ошибка №3: Путаница между коллекциями и массивами.
Коллекция — это не массив! У коллекции нет поля length, вместо этого используйте метод size(). У массива нет метода add(), у коллекции — нет оператора [] для доступа по индексу (только у списков через get(index)).
Ошибка №4: Ожидание, что порядок элементов всегда сохраняется.
Если вы используете Set или Map, порядок элементов не гарантируется (если только не используете специальные реализации вроде LinkedHashSet или TreeMap). Для упорядоченных данных используйте List или соответствующие коллекции.
Ошибка №5: Использование примитивных типов в коллекциях.
Коллекции могут хранить только объекты, а не примитивы. То есть нельзя создать List<int>, только List<Integer>. Не забывайте про классы-обёртки!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ