Коллекции. Практические Задания
Добавьте в TreeSet два ящика одинакового веса — и в коллекции останется только один. Если compareTo() сравнивает лишь поле weight, второй ящик считается дубликатом и молча отбрасывается, без исключения:
Set<HeavyBox> boxes = new TreeSet<>(); // compareTo() сравнивает только weight
boxes.add(new HeavyBox(10, 20, 30, 5));
boxes.add(new HeavyBox(40, 50, 60, 5));
System.out.println(boxes.size()); // Вывод: 1 На этой странице — 10 практических задач по коллекциям Java с примерами входных данных: ArrayList, TreeSet, HashSet, ArrayDeque, HashMap, Iterator и Comparable. Задачи идут в порядке уроков модуля «Коллекции»: от списков к множествам, очередям и отображениям Map, а последняя продолжает сквозной проект «Интернет-магазин». К каждой задаче есть разбор решения.
Какая коллекция нужна в каждой задаче
Каждая задача отрабатывает одну коллекцию и 2–3 её ключевых метода. Если метод из таблицы незнаком, сначала повторите урок из правого столбца — так решение займёт 20–40 минут, а не вечер с документацией.
| Задача | Коллекция и методы | Что повторить |
|---|---|---|
| Динамический массив | ArrayList: add(), get(), remove(), toArray(), clear() | Интерфейс List и ArrayList |
| TreeSet с сортировкой | TreeSet, Comparable.compareTo() | TreeSet, Comparable и Comparator |
| Набор чисел | HashSet / LinkedHashSet, String.split() | Set, HashSet и LinkedHashSet |
| union() и intersect() | addAll(), retainAll(), обобщённые методы | Интерфейс Collection |
| Очередь | ArrayDeque: offer(), poll() | Queue и Deque, ArrayDeque |
| Разделение коллекции | Iterator: hasNext(), next(), remove() | Iterator и ListIterator |
| HashMap книг | HashMap: entrySet(), keySet(), values() | Интерфейс Map |
| Студенты | Set, equals() / hashCode(), удаление через Iterator | Set и HashSet |
| Домашние животные | Map<String, Pet>, полиморфизм | Интерфейс Map |
| Интернет-магазин | List, Comparator, List.sort() / Collections.sort() | Методы класса Collections |
ArrayList: динамический массив из объектов HeavyBox
- Создать динамический массив (
ArrayList), содержащий объекты классаHeavyBox. - Класс HeavyBox наследует класс Box и содержит переменную int weight.
- Класс Box содержит переменные double width, double height, double depth.
- Распечатать его содержимое, используя
for each. - Изменить вес первого ящика на 1.
- Удалить последний ящик.
- Получить массив, содержащий ящики из коллекции, тремя способами и вывести его на консоль.
- Удалить все ящики.
Подсказка
Массив из коллекции получают методами toArray() (вернёт Object[]), toArray(new HeavyBox[0]) и, начиная с Java 11, toArray(HeavyBox[]::new). Типизированный массив HeavyBox[] дают только два последних. Для вывода массива удобен Arrays.toString().
TreeSet с сортировкой ящиков по весу
- Создать TreeSet, содержащий объекты класса
HeavyBox. - Класс HeavyBox наследует класс Box и содержит переменную int weight.
- Класс Box содержит переменные double width, double height, double depth.
HeavyBoxдолжен реализовать интерфейсComparable, сортировка должна осуществляться по переменной weight.- Распечатать содержимое с помощью
for each.
Удаление повторяющихся чисел из строки через Set
- Пользователь вводит набор чисел в виде одной строки "1, 2, 3, 4, 4, 5, 10, 11".
- Избавиться от повторяющихся элементов в строке.
- Вывести результат на экран.
- Используйте интерфейс Set.
Нюанс
HashSet не сохраняет порядок ввода. Чтобы вывести числа в исходной последовательности — 1, 2, 3, 4, 5, 10, 11 — возьмите LinkedHashSet. Строку удобно разбить через split("\\s*,\\s*"): так пробелы вокруг запятых не попадут в элементы, и "4" с " 4" не окажутся разными строками.
Объединение и пересечение множеств: union() и intersect()
- Напишите методы
static <T> Set<T> union(Set<T> set1, Set<T> set2)иstatic <T> Set<T> intersect(Set<T> set1, Set<T> set2), реализующие операции объединения и пересечения множеств. - Методы должны возвращать новое множество и не изменять
set1иset2. - Протестируйте работу этих методов на предварительно заполненных множествах.
Очередь ArrayDeque: методы offer() и poll()
- Создать очередь, содержащую объекты класса
HeavyBox. - Класс HeavyBox наследует класс Box и содержит переменную int weight.
- Класс Box содержит переменные double width, double height, double depth.
- Используйте класс
ArrayDeque. - Поместить объекты в очередь с помощью метода
offer(). - Удалить объекты методом
poll().
Разделение коллекции с помощью Iterator
- Создать коллекцию, содержащую объекты класса
Box.public class Box { private double width; private double height; private double depth; public Box(double width, double height, double depth) { this.width = width; this.height = height; this.depth = depth; } public double getWidth() { return width; } // getHeight(), getDepth() и toString() — аналогично } - Написать метод, который перебирает элементы коллекции и проверяет ширину коробок.
- Если ширина коробки больше 30 см, коробка перемещается в другую коллекцию.
- Для перебора элементов используйте итератор.
HashMap книг: entrySet(), keySet() и values()
- Создайте HashMap, содержащий пары значений — имя книги и объект книги (класс Book).
- Класс Book содержит переменные name, cost, author.
- Перебрать и распечатать пары значений —
entrySet(). - Перебрать и распечатать набор из имён книг —
keySet(). - Перебрать и распечатать значения книг —
values(). - Для каждого перебора создать свой метод.
Ещё один способ
После трёх обязательных вариантов попробуйте четвёртый — books.forEach((name, book) -> System.out.println(name + ": " + book)) (Java 8). Он короче, но внутри делает то же, что перебор entrySet().
Студенты: фильтрация по среднему баллу и перевод на курс
- Создать класс Student, содержащий следующие характеристики – имя, группа, курс, оценки по предметам.
- Создать коллекцию
Set<Student>, содержащую объекты класса Student. Переопределите в Student методыequals()иhashCode(). - Написать метод, который удаляет студентов со средним баллом < 3.
- Написать метод, который переводит студента на следующий курс, если средний балл >= 3.
- Напишите метод
printStudents(Set<Student> students, int course), который получает множество студентов и номер курса. Метод печатает на консоль имена тех студентов, которые обучаются на данном курсе.
Map домашних животных: имя и объект Pet
- Создайте класс
Petс переменной name и абстрактным методом makeNoise(). - Создайте наследников класса
Pet—Cat,Dog,Parrot. Каждый класс реализует свой вариант метода makeNoise(). - Создайте отображение из домашних животных, где в качестве ключа выступает имя животного, а в качестве значения — объект класса
Pet. - Добавьте в отображение разных животных.
- Создайте метод, выводящий на консоль все ключи отображения.
- Создайте метод, вызывающий метод makeNoise() для каждого животного.
Коллекции вместо массивов, сортировка каталога
Интернет-магазин · часть 6 из 13 · ← часть 5 · часть 7 →
- Вместо массивов используйте коллекции.
- Товары каталога должны быть отсортированы, например по цене. Для сортировки используйте
ComparatorиList.sort()илиCollections.sort().
На чём чаще всего ошибаются
Большинство ошибок в задачах по коллекциям не ломают компиляцию: код запускается, но теряет элементы, хранит дубликаты или падает с исключением только на определённых данных. Ниже — промахи, которые чаще всего встречаются в решениях этой страницы.
| Ошибка | Что произойдёт | Как исправить |
|---|---|---|
Удаление через list.remove(box) внутри for each | Как правило — ConcurrentModificationException на следующей итерации. Но если удалён предпоследний элемент, исключения не будет: цикл просто завершится и последний элемент останется непроверенным | Удалять через iterator.remove() или removeIf() (Java 8) |
compareTo() сравнивает только weight | TreeSet считает ящики одного веса одинаковыми и хранит только первый | Сравнивать дополнительные поля, если они равны по весу: Comparator.comparingInt(HeavyBox::getWeight).thenComparingDouble(Box::getWidth) |
Свой класс в HashSet или как ключ HashMap без equals() и hashCode() | Два одинаковых студента хранятся дважды, contains() для копии возвращает false | Переопределить оба метода (или использовать record, Java 16+) |
Ожидание порядка добавления от HashMap | Книги и животные выводятся в непредсказуемом порядке, который может меняться при росте таблицы | LinkedHashMap — порядок добавления, TreeMap — сортировка по ключу |
union() через set1.addAll(set2) | Метод «портит» исходное множество set1, и следующий вызов intersect() даёт неверный результат | Работать с копией: Set<T> result = new HashSet<>(set1); |
Изменение списка из List.of() или Arrays.asList() | UnsupportedOperationException при add()/remove() | Обернуть в изменяемый список: new ArrayList<>(List.of(...)). Подробнее — в уроке Backed Collections |
Проверь свой код
Объявляйте переменные через интерфейс (List<HeavyBox> boxes = new ArrayList<>()), а не через класс реализации, и не используйте сырые типы без <>. Остальные правила оформления — в чек-листе по оформлению кода.
Часто задаваемые вопросы
Какую коллекцию Java выбрать: List, Set, Queue или Map?
List — когда важен порядок и допустимы дубликаты (по умолчанию ArrayList). Set — когда нужны только уникальные элементы: HashSet самый быстрый, LinkedHashSet хранит порядок добавления, TreeSet сортирует. Queue/Deque — для обработки элементов по очереди или как стек (ArrayDeque). Map — когда значение ищется по ключу. Какая коллекция нужна в каждой задаче страницы — в таблице выше.
Какие задачи по коллекциям Java дают на собеседовании?
Чаще всего: убрать дубликаты из списка, найти пересечение двух множеств, удалить элементы во время перебора без ConcurrentModificationException, отсортировать объекты через Comparable или Comparator, посчитать частоту слов через HashMap и реализовать LRU-кэш. Первые четыре темы отрабатываются в задачах этой страницы, LRU-кэш разобран в уроке LinkedHashMap.
Можно ли решать эти задачи через Stream API?
Можно, но сначала решите их на «чистом» API коллекций: цель задач — отработать Iterator, entrySet(), retainAll() и сравнение объектов. Вариант со stream().filter() полезен как второе решение для сравнения, но он не объясняет, почему удаление в for each заканчивается исключением.
В каком порядке решать задачи и сколько времени они займут?
Порядок повторяет уроки модуля: ArrayList → TreeSet и HashSet → ArrayDeque → Iterator → HashMap → итоговая часть интернет-магазина. Одна задача занимает 20–60 минут, вся страница — около 5–6 часов.
Комментарии