Собеседование по Java: вопросы и три задачи с разбором
Блог

Собеседование по Java: вопросы и три задачи с разбором

7 просмотровОценить статью0 отзывов

На собеседовании по Java полезно уметь объяснить, что произойдёт с данными, и проверить решение на границе условий. В этом практикуме разберём три задачи по коллекциям: поиск по ключу, удаление элементов и сортировку. Материал подготовила редакция Mentoring.digital.

Содержание статьи

Как пройти практикум с пользой

Сначала прочитайте только условие, запишите ожидаемый результат и предложите решение. После этого сравните код с разбором. Если ответ совпал, измените входные данные: пустая коллекция, повторяющиеся значения, минимальное и максимальное целое число часто раскрывают незамеченное условие.

Примеры рассчитаны на Java 17 и новее. В них используются записи record и метод Stream.toList(). Это учебные задания, а не подборка подтверждённых вопросов конкретного работодателя. Для запуска нужны импорты java.util.ArrayList, Comparator, HashMap, List, Map и Objects из пакета java.util. Методы и записи можно разместить внутри одного класса.

Задача 1. Почему HashMap не находит похожий ключ

Условие: в карте хранятся владельцы по идентификатору. В неё добавили пользователя с ID 7, а при чтении создали другой объект с тем же ID. Получите имя «Ирина», не перебирая все записи карты.

record UserKey(long id) {}

    static String findOwner() {
        Map<UserKey, String> owners = new HashMap<>();
        owners.put(new UserKey(7), "Ирина");
        return owners.get(new UserKey(7));
    }

Здесь два объекта new UserKey(7) равны по значению компонента записи. Сгенерированные для этой записи equals() и hashCode() согласованы, поэтому поиск по новому равному ключу возвращает сохранённое имя. Если вместо записи взять обычный класс без переопределения этих методов, унаследованный Object.equals() сравнивает ссылки: два отдельных экземпляра не становятся равными из-за одинакового поля.

Договор равенства требует, чтобы равные объекты имели одинаковый хеш-код. Обратное неверно: одинаковый хеш ещё не доказывает равенство. При собственной реализации класса согласованно определяйте оба метода. Изменение поля, участвующего в равенстве и вычислении хеша уже используемого ключа, может нарушить ожидаемый поиск в карте.

  • Проверьте поиск по ID 7 и по отсутствующему ID 8. Во втором случае в этой карте результатом будет null.
  • Сравните два ключа с одинаковыми и разными ID. Для равных ключей отдельно сравните хеши.
  • Объясните, почему одна лишь замена HashMap на другую реализацию карты не исправляет неверно заданное равенство.

Задача 2. Удалить выполненные задачи и сохранить исходный список

Дан список задач A, B, C, D. У A и C признак done равен true. Требуется вернуть новый изменяемый список B, D с прежним порядком элементов. Исходный список менять нельзя. Контракт этого примера допускает только непустые ссылки на задачи, а сам список не должен быть null.

record Task(String name, boolean done) {}

    static List<Task> openTasks(List<Task> source) {
        Objects.requireNonNull(source);
        List<Task> result = new ArrayList<>(source);
        result.removeIf(Task::done);
        return result;
    }

Копирование создаёт отдельный контейнер, после чего removeIf удаляет из него элементы, для которых предикат истинен. Исходный контейнер остаётся прежним. Это поверхностная копия: в общем случае объекты внутри двух списков общие. В примере запись Task содержит строку и логический признак, а её компоненты после создания не переназначаются.

Удалять элементы напрямую из того же ArrayList внутри расширенного цикла for нельзя считать корректным решением. Итератор может обнаружить структурное изменение и выбросить ConcurrentModificationException, но исключение не гарантировано для любого такого обхода. Проверка должна оценивать результат и сохранность исходных данных, а не только отсутствие ошибки.

  • Сравните исходный список с его снимком до вызова.
  • Проверьте пустой список, список без выполненных задач и список, где выполнены все задачи.
  • Добавьте элемент в результат и убедитесь, что исходный контейнер не изменился. Если нужна неизменяемая выдача, это отдельное условие контракта.

Задача 3. Отсортировать приоритеты без ошибки на больших числах

У заявок есть строковый ID и целочисленный приоритет. Нужен новый список по убыванию приоритета. При равенстве приоритетов упорядочьте заявки по ID по естественному порядку строк. Входной список, его элементы и ID не равны null.

record Ticket(String id, int priority) {}

    static List<Ticket> orderedTickets(List<Ticket> source) {
        Comparator<Ticket> order = Comparator
                .comparingInt(Ticket::priority).reversed()
                .thenComparing(Ticket::id);
        return source.stream().sorted(order).toList();
    }

Сравнение через вычитание b.priority() - a.priority() опасно: результат может переполнить диапазон int и дать неверный знак. comparingInt задаёт сравнение целых чисел, reversed() меняет порядок по приоритету, а thenComparing определяет порядок при совпадении этого поля.

Для входа low: MIN_VALUE, B: 0, high: MAX_VALUE, A: 0 ожидаемый порядок ID: high, A, B, low. Исходный список не переставляется. Результат Stream.toList() неизменяемый: попытка добавить в него элемент вызывает UnsupportedOperationException. Если по условию нужен изменяемый контейнер, явно создайте из результата ArrayList.

Какие вопросы стоит уметь объяснить после решения

ВопросЧто должно быть в ответе
Чем равенство по ссылке отличается от равенства по значению?Какие объекты считаются одинаковыми в модели и как это выражено в equals/hashCode.
Что именно копируется в new ArrayList<>(source)?Новый контейнер с теми же ссылками на элементы; это не глубокое копирование.
Чем отличаются фильтрация и изменение исходного списка?Побочные эффекты должны соответствовать явному условию задачи.
Зачем нужен второй критерий сортировки?Он определяет результат для равных приоритетов.
Достаточно ли успешного запуска на одном наборе?Нет. Нужны граничные случаи, проверки контракта и объяснение ограничений.

Редакция скомпилировала эти примеры с целевым уровнем Java 17 и выполнила 15 проверок, включая равенство ключей, сохранность входного списка, крайние приоритеты и неизменяемость результата сортировки. Эти проверки относятся к опубликованным учебным условиям; они не подтверждают готовность ко всему техническому интервью.

Для самостоятельного продолжения измените одно условие: разрешите одинаковые ID или задайте правила для отсутствующего приоритета. Сначала определите ожидаемое поведение, затем меняйте код и проверки. Разобрать собственные решения можно с наставником по Java, а выстроить последовательную практику помогут курсы Java.

Мнение читателей

Оценки и отзывы о статье

Оставить отзыв

Как вам статья?

Поставьте оценку. При желании добавьте отзыв или вопрос по статье.

Ваша оценка
5 из 5
0 / 3 000

После одобрения имя, оценка и отзыв будут видны другим читателям. Политика конфиденциальности

Отзывы читателей0

Здесь пока нет отзывов. Расскажите, чем вам помогла статья.

Все статьи