Подборка вопросов

Вопросы на собеседовании Java middle

Вопросы уровня middle — многопоточность, JVM, коллекции изнутри, Stream API.

165вопросов
  1. 01Чем checked-исключения отличаются от unchecked?

    Checked (наследники Exception, кроме RuntimeException) компилятор требует объявить в throws или обработать. Unchecked (RuntimeException и Error) — нет. Выбор: checked — когда…

    Middle
  2. 02Какое правило связывает equals() и hashCode()?

    Равные по equals объекты обязаны иметь равный hashCode; обратное не требуется — коллизии нормальны. Иначе HashMap и HashSet ищут в другой корзине и не находят равный объект: до…

    Middle
  3. 03Что гарантирует ключевое слово volatile для переменной?

    volatile даёт видимость (запись сразу видна другим потокам) и запрет переупорядочивания вокруг обращения, но не атомарность: count++ на volatile-поле всё равно теряет обновления.

    Middle
  4. 04Почему String в Java неизменяемый?

    Неизменяемость String даёт пул строк (литералы разделяются безопасно), кэш hashCode (строка — идеальный ключ HashMap), потокобезопасность без синхронизации и безопасность…

    Middle
  5. 05Чем интерфейс отличается от абстрактного класса и что изменили default-методы?

    Интерфейс — контракт: класс может реализовать много интерфейсов, состояния (полей экземпляра) нет. Абстрактный класс — общая база с состоянием, конструктором и частичной…

    Middle
  6. 06Чем промежуточные операции Stream отличаются от терминальных?

    Промежуточные операции (filter, map, sorted) ленивы и возвращают новый Stream — они только описывают конвейер. Терминальная (collect, forEach, count, findFirst) запускает…

    Middle
  7. 07Чем HashMap отличается от Hashtable и ConcurrentHashMap?

    HashMap — не потокобезопасна, допускает один null-ключ и null-значения. Hashtable — устаревшая, все методы synchronized, null запрещён. ConcurrentHashMap — потокобезопасная с…

    Middle
  8. 08Что происходит в HashMap при коллизии ключей?

    Коллизии кладутся в один bucket; HashMap ищет нужный ключ через equals, а длинную цепочку (≥8 при таблице ≥64) превращает в красно-чёрное дерево.

    Middle
  9. 09Чем volatile отличается от synchronized?

    volatile — видимость и порядок для одной переменной без блокировки. synchronized — видимость плюс взаимное исключение: блок целиком выполняется одним потоком, поэтому составные…

    Middle
  10. 10Чем Comparable отличается от Comparator и что значит согласованность порядка с equals?

    Comparable — естественный порядок, который задаёт сам класс (compareTo), один. Comparator — внешний порядок, их может быть сколько угодно, комбинируются через…

    Middle
  11. 11Какое свойство LinkedHashMap отличает его от HashMap?

    LinkedHashMap — HashMap плюс двусвязный список записей: обход в порядке вставки (по умолчанию) или в порядке доступа (accessOrder = true).

    Middle
  12. 12Чем IO отличается от NIO?

    IO (java.io) — потоки байт и символов, блокирующие: чтение держит поток, модель «поток на соединение». NIO (java.nio) — каналы и буферы, неблокирующий режим и Selector: один поток…

    Middle
  13. 13Зачем нужен serialVersionUID?

    serialVersionUID — версия класса для встроенной сериализации. При несовпадении версии в потоке и у локального класса — InvalidClassException. Если не объявить, JVM вычислит её из…

    Middle
  14. 14Как правильно использовать Optional?

    Optional — тип возвращаемого значения «результата может не быть», видимый в сигнатуре. Распаковывают через map, flatMap, filter, orElseGet, orElseThrow, а не isPresent() + get()…

    Middle
  15. 15Чем map, flatMap и filter отличаются в Stream API?

    map — один элемент → один элемент (преобразование). flatMap — один элемент → поток элементов, все потоки разворачиваются в один. filter — оставляет элементы, удовлетворяющие…

    Middle
  16. 16Чем LocalDateTime отличается от ZonedDateTime?

    LocalDateTime — дата и время без зоны: «15 марта, 09:00» неизвестно где. ZonedDateTime — с ZoneId и правилами перехода на летнее время: конкретный момент. Instant — момент на…

    Middle
  17. 17В чём опасность ThreadLocal в пуле потоков?

    Поток в пуле переиспользуется: значение ThreadLocal, не очищенное после задачи, протекает в следующую задачу (чужой пользователь, транзакция) и удерживает память. Правило: try {…

    Middle
  18. 18Что такое deadlock и как его предотвращать?

    Deadlock — циклическое ожидание: поток A держит замок 1 и ждёт замок 2, поток B держит 2 и ждёт 1. Предотвращают единым порядком захвата, tryLock с таймаутом и откатом, короткими…

    Middle
  19. 19Чем различаются CountDownLatch, CyclicBarrier и Semaphore?

    CountDownLatch — одноразовое ожидание N событий: дошёл до нуля — открыт навсегда. CyclicBarrier — переиспользуемая точка встречи N потоков между раундами. Semaphore — ограничение…

    Middle
  20. 20Что такое class loader и как работает делегирование загрузки классов?

    ClassLoader находит байт-код и превращает его в класс. Иерархия: Bootstrap (ядро JDK) → Platform (модули платформы) → Application (classpath). Модель parent-first: запрос сначала…

    Middle
  21. 21Какой инструмент обычно используют для корректных Java microbenchmarks?

    JMH (Java Microbenchmark Harness) от разработчиков OpenJDK: учитывает прогрев, форки JVM, устранение мёртвого кода, свёртку констант, статистику по итерациям.

    Middle
  22. 22Реализуй потокобезопасный счётчик Counter с методами increment() и get().

    Проще всего — AtomicInteger: incrementAndGet() и get(), без блокировок. Альтернатива — synchronized на обоих методах (важно: и на чтении тоже, иначе нет видимости).

    Middle
  23. 23Почему int v = flag ? map.get(key) : 0 (map.get может вернуть null) способно бросить NPE?

    Если одна ветвь тернарного оператора int, а другая Integer, тип всего выражения — int: обёрточная ветвь распаковывается, и null даёт NPE, хотя код выглядит безопасным.

    Middle
  24. 24Чем int[] на миллион чисел выгоднее List<Integer> того же размера?

    int[] — сплошной блок ~4 МБ. List<Integer> — миллион отдельных объектов Integer (16 байт каждый) плюс массив ссылок: в 4–5 раз больше памяти, нагрузка на GC и промахи кэша при…

    Middle
  25. 25Почему стек реализуют через ArrayDeque, а не java.util.Stack?

    Стек и очередь в одном потоке — ArrayDeque (кольцевой массив, O(1) по краям, данные подряд). Stack наследует Vector: synchronized на каждой операции и доступ по индексу в середину…

    Middle
  26. 26В каком порядке выдаёт элементы итерация (for-each) по PriorityQueue?

    Итерация по PriorityQueue не отсортирована: куча гарантирует только «родитель ≤ детей». Отсортированный порядок даёт лишь повторный poll().

    Middle
  27. 27Какая алгоритмическая сложность операций PriorityQueue (бинарной кучи)?

    offer и poll — O(log n) (просеивание вверх и вниз), peek — O(1) (корень), remove(Object) и contains — O(n) (линейный поиск).

    Middle
  28. 28Какое ограничение Future решает CompletableFuture?

    Future — дескриптор результата с единственным способом получить значение: блокирующий get(). CompletableFuture позволяет описать цепочку продолжений (thenApply, thenCompose…

    Middle
  29. 29Чем thenCompose отличается от thenApply в CompletableFuture?

    thenApply — как map: функция значение → значение. thenCompose — как flatMap: функция значение → новый CompletableFuture, результат «разворачивается». Без thenCompose получилось бы…

    Middle
  30. 30Каков компромисс трёх базовых алгоритмов GC: mark-sweep, mark-compact, copying?

    Mark-sweep — пометить живых, освободить остальное: быстро, но фрагментация. Mark-compact — плюс уплотнение живых: нет фрагментации, но перемещение дорого. Copying — копировать…

    Middle
  31. 31Что показывают метрики allocation rate и promotion rate?

    Allocation rate — сколько МБ/с приложение создаёт объектов: чем выше, тем чаще minor GC. Promotion rate — сколько МБ/с переезжает в старое поколение: чем выше, тем чаще old/full…

    Middle
  32. 32Чем this внутри лямбды отличается от this внутри анонимного класса?

    В лямбде this — окружающий объект: она не вводит своей области видимости. В анонимном классе this — сам анонимный объект, и его поля могут перекрывать внешние. Лямбда…

    Middle
  33. 33Почему лямбда может захватывать только effectively final локальные переменные?

    Лямбда захватывает значение локальной переменной (копию), а не ячейку: локальная переменная живёт в кадре стека и исчезает вместе с методом, а лямбда может жить дольше и…

    Middle
  34. 34Чем collect отличается от reduce при сборке стрима?

    reduce — неизменяемая свёртка: из двух значений получается новое (сумма, максимум). collect — изменяемая свёртка: элементы накапливаются в один контейнер (список, карта…

    Middle
  35. 35Что произойдёт в Collectors.toMap, если два элемента дают одинаковый ключ, а merge-функция не передана?

    IllegalStateException: Duplicate key. При возможных дубликатах передают третий аргумент — функцию слияния: (a, b) -> a, сумма, конкатенация.

    Middle
  36. 36Как одним коллектором получить «количество элементов в каждой группе»?

    groupingBy(classifier, counting()) — downstream-коллектор counting сворачивает каждую группу в число (Long).

    Middle
  37. 37Чем switch-выражение (case L -> …) надёжнее старого switch?

    Стрелочный case L -> не проваливается и не требует break; switch-выражение возвращает значение (для блока — yield); по enum и sealed-типам компилятор проверяет полноту — забытый…

    Middle
  38. 38Чем Instant и LocalDateTime отличаются и когда брать Duration, а когда Period?

    Instant — момент на шкале (UTC, от эпохи); LocalDateTime — дата и время без зоны, моментом не является. Duration — машинное время в секундах и наносекундах, Period — календарные…

    Middle
  39. 39Что требуется, чтобы класс был ПО-НАСТОЯЩЕМУ неизменяемым?

    Рецепт: все поля private final, нет сеттеров и других мутаторов, запрет наследования (final-класс или приватный конструктор с фабриками), защитные копии изменяемых данных на входе…

    Middle
  40. 40Конструктор сохранил переданный List по ссылке (this.items = items). Почему объект всё равно изменяем?

    Поле хранит чужую ссылку: вызывающий меняет список снаружи, и «неизменяемый» объект меняется. final запрещает переприсвоить поле, но не менять содержимое. Нужна защитная копия на…

    Middle
  41. 41Почему про immutable-объект говорят «потокобезопасен без синхронизации»?

    Модель памяти гарантирует: если все поля final и this не утёк из конструктора, любой поток, получивший ссылку на готовый объект, увидит поля проинициализированными — без…

    Middle
  42. 42Как в immutable-дизайне моделируют «изменение» и снижают его цену?

    «Изменение» — новый объект: методы withX возвращают копию с одним изменённым полем. Для частых правок — изменяемый Builder, отдающий неизменяемый результат, или…

    Middle
  43. 43Чего record НЕ делает за вас при проектировании неизменяемого носителя данных?

    Record делает компоненты private final и генерирует конструктор, аксессоры, equals, hashCode, toString, но не делает защитных копий: изменяемый компонент (List, массив, Date)…

    Middle
  44. 44В коде расчёта комиссии есть метод с цепочкой if по типу платежа, и при добавлении каждого нового способа оплаты приходится править этот метод и ещё три похожих. Какой принцип SOLID нарушен в первую очередь?

    Open/Closed Principle: новое поведение требует правки существующего кода, а не добавления нового. Растущая цепочка if или switch по типу, повторённая в нескольких местах, …

    Middle
  45. 45Что такое Liskov Substitution Principle и что обязан соблюдать подтип?

    Подтип должен быть подставим вместо базового типа без сюрпризов для вызывающего: не усиливать предусловия, не ослаблять постусловия, сохранять инварианты, не бросать новых…

    Middle
  46. 46Сервис получает через конструктор зависимость типа PostgresOrderRepository (конкретный класс), которую внедряет Spring. Что здесь верно?

    DI есть, DIP нарушен: зависимость приходит снаружи (техника внедрения), но сервис зависит от конкретного класса инфраструктуры, а не от абстракции. DIP — принцип: верхний уровень…

    Middle
  47. 47Что утверждает Interface Segregation Principle?

    Клиенты не должны зависеть от методов, которыми не пользуются: лучше несколько узких интерфейсов под роли, чем один толстый. Толстый интерфейс создаёт ложную связанность, а…

    Middle
  48. 48Два метода расчёта скидки — для розницы и для опта — сегодня содержат идентичный код, но правила задают разные владельцы и они уже расходились в прошлом. Что правильнее сделать?

    Оставить дублирование: совпал код, но не знание. Правила меняются по разным причинам и разными владельцами — объединение создаст управляющую связанность: первое расхождение даст…

    Middle
  49. 49Что верно про YAGNI?

    YAGNI — не строить под несуществующие требования. Цена преждевременной фичи: постройка, задержка нужного, сопровождение лишнего кода и исправление, если угадали неверно. На тесты…

    Middle
  50. 50Какой из фрагментов нарушает закон Деметры?

    Нарушение — путешествие по графу чужих объектов: order.getCustomer().getAddress().getCity().getName() фиксирует в вызывающем коде всю структуру, и любое изменение по пути его…

    Middle
  51. 51Что верно про связность (cohesion) и связанность (coupling)?

    Связность (cohesion) — насколько элементы модуля служат одной задаче: хотим высокую. Связанность (coupling) — насколько модуль завязан на устройство других: хотим низкую.

    Middle
  52. 52Что такое anemic domain model, чем она плоха и когда всё-таки допустима?

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

    Middle
  53. 53Чем Integer.valueOf(127) отличается от паттерна Factory Method по GoF?

    Factory Method (GoF) построен на наследовании: базовый класс объявляет метод создания, а какой продукт создать — решает подкласс. Integer.valueOf — статическая фабрика (идиома…

    Middle
  54. 54Какие преимущества даёт статическая фабрика по сравнению с публичным конструктором?

    Три плюса из Effective Java: имя (of, copyOf, ofNullable — различимы, в отличие от конструкторов с одной сигнатурой), не обязана создавать новый объект (кэш, синглтон), может…

    Middle
  55. 55Почему паттерн Builder особенно удобен при создании неизменяемых объектов?

    У неизменяемого объекта без билдера два плохих варианта: сеттеры (и он уже изменяем) или конструктор с длинным списком однотипных аргументов. Builder собирает состояние по…

    Middle
  56. 56Что отличает Abstract Factory от обычной фабрики?

    Abstract Factory создаёт семейство связанных объектов, согласованных между собой, так что клиент не смешает объекты разных семейств. Одна фабрика одного продукта — это ещё не…

    Middle
  57. 57Чем поверхностное копирование отличается от глубокого и как правильно копировать объекты в современной Java?

    Поверхностная копия копирует значения полей — то есть ссылки: вложенный изменяемый список общий у оригинала и копии. Глубокая — копирует весь граф. clone() — неудачный дизайн…

    Middle
  58. 58По какому признаку проще всего отличить Adapter от Decorator и Proxy?

    По интерфейсу: адаптер меняет интерфейс (InputStreamReader превращает байтовый поток в символьный), декоратор и прокси сохраняют его. Механизм у всех трёх один — композиция и…

    Middle
  59. 59Какой паттерн лежит в основе конструкции new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))?

    Decorator: каждая обёртка добавляет один аспект (буферизацию, распаковку) и остаётся тем же InputStream. Комбинацию выбирает клиент во время выполнения — без взрыва числа…

    Middle
  60. 60Spring оборачивает бины в прокси, чтобы работали @Transactional и @Cacheable. Какие практические следствия из этого вытекают?

    Прокси перехватывает только внешние вызовы: this.method() внутри класса идёт мимо прокси — аннотация не сработает. CGLIB не проксирует final-классы и final-методы, JDK-прокси…

    Middle
  61. 61Что произойдёт при вызове add на списке, полученном из Arrays.asList(array)?

    UnsupportedOperationException: Arrays.asList — адаптер над массивом фиксированного размера. add и remove не поддержаны, а set пишет прямо в массив (и изменения массива видны в…

    Middle
  62. 62Какой паттерн реализуют SLF4J и JdbcTemplate по отношению к тому, что они скрывают?

    Facade — простой вход в сложную подсистему. SLF4J — Simple Logging Facade for Java. JdbcTemplate скрывает ритуал JDBC: соединение, statement, обработка SQLException, закрытие…

    Middle
  63. 63Чем паттерн Proxy отличается от Decorator, если у обоих тот же интерфейс, что и у обёрнутого объекта?

    Структурно почти одинаковы, различие — в намерении: декоратор добавляет поведение, и цепочку собирает клиент; прокси управляет доступом к объекту (ленивое создание, права, кэш…

    Middle
  64. 64Какой паттерн представляет java.util.Comparator?

    Strategy: алгоритм сравнения передаётся снаружи, сортировка при этом не меняется.

    Middle
  65. 65В чём принципиальная разница между Template Method и Strategy?

    Template Method — наследование на этапе компиляции: скелет алгоритма в базовом классе, подкласс заполняет шаги. Strategy — композиция во время выполнения: алгоритм передаётся…

    Middle
  66. 66Что верно про реализацию паттерна Observer в современной Java?

    java.util.Observable устарел с Java 9. Современные формы: ApplicationEventPublisher и @EventListener в Spring, реактивные потоки (Flow, Reactor), брокеры сообщений. Подводные…

    Middle
  67. 67Какой паттерн реализуют цепочка сервлетных фильтров и фильтр-цепочка Spring Security?

    Chain of Responsibility: запрос идёт по звеньям, и каждое решает, обработать ли его и передавать ли дальше (chain.doFilter). Возможность прервать цепочку — отличие от декоратора…

    Middle
  68. 68State и Strategy структурно почти одинаковы. Что их различает?

    Кто управляет подстановкой: стратегию выбирает клиент снаружи, и она обычно не меняется; состояние объект меняет сам в ответ на события, и переходы — часть его логики.

    Middle
  69. 69Поток пытается войти в synchronized-блок, занятый другим потоком. В каком состоянии он находится?

    BLOCKED — ожидание входа в занятый монитор synchronized. Шесть состояний: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.

    Middle
  70. 70Что верно про прерывание потока через interrupt()?

    interrupt() — просьба, а не приказ: выставляет флаг; блокирующие sleep, wait, join бросают InterruptedException и сбрасывают флаг. Поток проверяет флаг сам и завершается в…

    Middle
  71. 71Что верно про daemon-потоки?

    JVM завершается, когда остались только daemon-потоки; они обрываются без выполнения finally. Флаг ставится до start(), иначе IllegalThreadStateException.

    Middle
  72. 72Почему фабрики из класса Executors считают опасными в production-коде?

    Скрытые неограниченные ресурсы: newFixedThreadPool — неограниченная очередь (задачи копятся до OutOfMemoryError, наружу не идёт никакого отказа), newCachedThreadPool …

    Middle
  73. 73Сервис в основном ходит по сети: на каждую задачу примерно 90% времени — ожидание ответа и 10% — вычисления. Как выбрать размер пула потоков?

    IO-bound: ядра × (1 + W/C), где W — ожидание, C — вычисления; при 90/10 — около 10 × ядер. CPU-bound — примерно по числу ядер. Это ориентир: реальный предел часто задаёт внешний…

    Middle
  74. 74Задача, отправленная в пул через submit(), бросает RuntimeException, но в логах ничего нет. Почему?

    submit() прячет исключение в Future: оно появится только при get() в ExecutionException. Если результат никто не запрашивает — ошибка исчезает бесследно. execute() пропускает…

    Middle
  75. 75Какие пары действий образуют отношение happens-before?

    Happens-before — гарантия, что результаты A видны в B. Пары: порядок внутри потока, unlock → последующий lock того же монитора, запись volatile → последующее чтение того же поля…

    Middle
  76. 76Нужно ограничить число одновременных обращений к внешнему API десятью, не ограничивая при этом число рабочих потоков. Какой примитив подходит?

    Semaphore с десятью разрешениями: acquire перед вызовом, release в finally. Он ограничивает число одновременных доступов к ресурсу, не трогая число потоков.

    Middle
  77. 77Можно ли переиспользовать CountDownLatch после того, как счётчик дошёл до нуля?

    Нет: дошедший до нуля CountDownLatch открыт навсегда, метода сброса нет. Для повторяющихся раундов — CyclicBarrier или Phaser; либо новый latch на каждый раунд.

    Middle
  78. 78В коде вызывается semaphore.acquire(), затем работа с ресурсом, затем semaphore.release() в конце метода. Что здесь опасно?

    release не в finally: исключение навсегда съедает разрешение. С каждым сбоем параллелизм падает на единицу, пока система не встанет без единой записи в логе.

    Middle
  79. 79Что верно про практическое применение виртуальных потоков?

    Не пулить (поток на задачу), применять для блокирующего ввода-вывода, помнить, что ThreadLocal на миллионах потоков дорог, и ограничивать доступ к внешним ресурсам семафором — пул…

    Middle
  80. 80Что происходит с виртуальным потоком, когда он выполняет блокирующий сетевой вызов?

    Unmount: стек виртуального потока (continuation) сохраняется в куче, несущий поток освобождается для других задач. Когда данные пришли — mount обратно, возможно на другой несущий…

    Middle
  81. 81На какой гипотезе построено разделение кучи на поколения?

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

    Middle
  82. 82Зачем в молодом поколении две области Survivor, а не одна?

    Копирующему сборщику нужна пустая область назначения: живые из Eden и занятого Survivor копируются в свободный Survivor, после чего Eden и бывший Survivor очищаются целиком, а…

    Middle
  83. 83В приложении участились длинные паузы full GC, при этом старое поколение почти всегда заполнено. О чём это говорит?

    Живых данных больше, чем помещается. Смотрят на занятость после каждого full GC: ползёт вверх — утечка, держится высоко, но стабильно — кучи мало под рабочий набор. Лечат причину…

    Middle
  84. 84Что верно про типы ссылок в Java?

    Strong — не собирается, пока достижим. Soft — очищается при нехватке памяти (кэш, который не жалко). Weak — на ближайшей сборке, если нет сильных ссылок (WeakHashMap, метаданные)…

    Middle
  85. 85Что относится к GC roots — корням достижимости?

    Корни — точки начала обхода: локальные переменные и параметры в стеках живых потоков, статические поля загруженных классов, JNI-ссылки, сами активные потоки и удерживаемые…

    Middle
  86. 86Почему finalize() признан неудачным механизмом и что использовать вместо него?

    finalize не гарантирует ни вызова, ни времени, замедляет сборку (объект переживает лишний цикл) и может «воскресить» объект. Устарел в Java 9, помечен к удалению в Java 18…

    Middle
  87. 87Нужна структура с быстрым поиском по ключу, которая при обходе отдаёт элементы в порядке их добавления. Что выбрать?

    LinkedHashMap: поиск по ключу O(1) и обход в порядке добавления.

    Middle
  88. 88Что верно про неизменяемые и защитные коллекции?

    List.of и List.copyOf — настоящие неизменяемые коллекции, null запрещён. Collections.unmodifiableList — представление: через исходную ссылку список по-прежнему меняется. Объекты…

    Middle
  89. 89Почему добавление в конец ArrayList считается амортизированно O(1), хотя иногда требует копирования всего массива?

    Ёмкость растёт в 1,5 раза: копирования всё реже, сумма копирований на n вставок — геометрическая прогрессия, то есть O(n). На одну вставку — константа в среднем, хотя отдельная…

    Middle
  90. 90Сколько стоит удаление элемента из середины ArrayList и почему?

    O(n): хвост сдвигается влево через System.arraycopy, последняя ячейка обнуляется. Удаление в цикле — квадратичная работа.

    Middle
  91. 91Что верно про управление ёмкостью ArrayList?

    Ёмкость растёт, но не уменьшается сама; clear() обнуляет ссылки, а массив остаётся прежнего размера. Пустой ArrayList без аргументов выделяет массив лениво — при первом добавлении…

    Middle
  92. 92Почему утверждение «вставка в середину LinkedList работает за O(1)» вводит в заблуждение?

    O(1) — только перецепление ссылок. Чтобы вставить по индексу, сначала нужно дойти до позиции — O(n). Итого add(i, x) линейный и у LinkedList, и у ArrayList.

    Middle
  93. 93Почему ArrayList обычно обходит LinkedList даже там, где асимптотика формально в пользу связного списка?

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

    Middle
  94. 94Нужна очередь FIFO внутри одного потока. Что выбрать по умолчанию?

    ArrayDeque: кольцевой массив, offer и poll — O(1), без узла на элемент и промахов кэша.

    Middle
  95. 95Как получить LRU-кэш на базе LinkedHashMap?

    new LinkedHashMap<>(cap, 0.75f, true) (accessOrder) + переопределённый removeEldestEntry, возвращающий size() > max. Get переносит запись в конец, самая давно неиспользуемая — в…

    Middle
  96. 96Какой ценой LinkedHashMap поддерживает предсказуемый порядок обхода по сравнению с HashMap?

    Цена — две дополнительные ссылки на запись и поддержка списка при вставке и удалении. get и put остаются O(1); обход даже быстрее — по списку, а не по всем корзинам.

    Middle
  97. 97Что произойдёт при обходе LinkedHashMap, созданного с accessOrder = true, если во время итерации вызвать get() по существующему ключу?

    В режиме accessOrder даже get переносит запись в конец — это структурная модификация, итератор бросит ConcurrentModificationException.

    Middle
  98. 98Как устроен HashSet внутри?

    HashSet — это HashMap: элементы — ключи, значение — общий объект-заглушка. LinkedHashSet построен на LinkedHashMap, TreeSet — на TreeMap.

    Middle
  99. 99В TreeSet добавили два объекта, для которых equals возвращает false, но компаратор считает их равными. Что произойдёт?

    Второй объект не будет добавлен: TreeSet считает элементы равными, если сравнение даёт 0, equals не вызывается.

    Middle
  100. 100Объект добавили в HashSet, после чего изменили у него поле, участвующее в hashCode. Что теперь вернёт contains для этого же объекта?

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

    Middle
  101. 101В цикле for-each по списку вызывается list.remove(element). Что произойдёт?

    ConcurrentModificationException — даже в одном потоке: for-each идёт через итератор, а list.remove меняет коллекцию мимо него; итератор сверяет modCount и падает.

    Middle
  102. 102Какие способы удалить элементы по условию во время обхода коллекции корректны?

    Корректно: removeIf, явный Iterator.remove(), проход по индексам с конца. Удаление в for-each — CME, по индексам вперёд — пропуск элементов.

    Middle
  103. 103Чем ListIterator отличается от обычного Iterator?

    ListIterator — только для списков: ход в обе стороны (hasPrevious, previous), индексы (nextIndex), изменение на месте — set и add.

    Middle
  104. 104Нужно быстро находить ближайшую запись с ключом не больше заданного и выбирать все записи в диапазоне дат. Какая структура подходит?

    TreeMap как NavigableMap: floorKey/ceilingKey/lowerKey/higherKey и subMap, headMap, tailMap за O(log n). Хеш-таблица порядок не хранит.

    Middle
  105. 105Что произойдёт при попытке положить null-ключ в TreeMap?

    NullPointerException: TreeMap сравнивает ключи, а null сравнить естественным порядком нельзя. HashMap допускает один null-ключ.

    Middle
  106. 106Какие требования входят в контракт equals?

    Рефлексивность (a.equals(a)), симметричность, транзитивность, согласованность (повторные вызовы дают одно и то же) и a.equals(null) == false. Самое частое нарушение …

    Middle
  107. 107Метод принимает StringBuilder и внутри выполняет sb.append("x"), а затем sb = new StringBuilder(). Что увидит вызывающий код?

    Вызывающий увидит добавленный символ, но не новый объект: Java всегда передаёт по значению, а для ссылочных типов значение — копия ссылки. Мутация объекта по копии видна всем…

    Middle
  108. 108У списка есть перегрузки remove(int index) и remove(Object o). Что сделает list.remove(1) для List<Integer>?

    Удалит элемент с индексом 1: перегрузка выбирается на компиляции, и remove(int) подходит без упаковки — на первой фазе подбора. Удалить значение 1 …

    Middle
  109. 109Что верно про varargs?

    Varargs — сахар над массивом: внутри параметр — обычный массив, он единственный и последний, без аргументов приходит пустой массив, а не null. Каждый вызов выделяет массив …

    Middle
  110. 110В try-with-resources исключение бросают и тело блока, и метод close(). Какое исключение получит вызывающий код?

    Наверх идёт исключение из тела — оно о настоящей причине. Исключение из close() прикрепляется к нему как suppressed (getSuppressed(), видно в стектрейсе). Ручной try/finally терял…

    Middle
  111. 111Чем интерфейс AutoCloseable отличается от Closeable?

    AutoCloseable (Java 7) — для любых ресурсов, close() бросает Exception. Closeable (java.io, старше) — его наследник под ввод-вывод: close() бросает IOException и обязан быть…

    Middle
  112. 112Код открывает соединение, затем в том же try создаёт из него statement, и оба объявлены в скобках try-with-resources. В каком порядке они закроются?

    Сначала statement, потом соединение — в обратном порядке объявления, как раскручивается стек: зависимый ресурс закрывается раньше того, из которого получен.

    Middle
  113. 113Почему List<String> нельзя присвоить переменной типа List<Object>?

    Дженерики инвариантны: если бы List<Object> objs = strings компилировалось, через objs можно было бы положить Integer, а потом получить ClassCastException при чтении из списка…

    Middle
  114. 114Что можно делать со списком, объявленным как List<? extends Number>?

    Читать как Number можно, добавлять нельзя ничего, кроме null: за ссылкой может быть List<Integer> или List<Double>, и компилятор не знает какой. Симметрично List<? super Integer>…

    Middle
  115. 115Метод должен перекладывать элементы из источника в приёмник. Какая сигнатура правильна по правилу PECS?

    void copy(List<? super T> dest, List<? extends T> src): источник производит — extends, приёмник потребляет — super. Так объявлен Collections.copy.

    Middle
  116. 116Что верно про record в Java?

    Компилятор генерирует private final поля, канонический конструктор, аксессоры (name(), без get), equals, hashCode, toString по всем компонентам. Record неявно final, наследует…

    Middle
  117. 117Когда record — неудачный выбор?

    Record прозрачен: компоненты — публичный контракт. Не подходит для изменяемых сущностей со скрытым представлением и охраняемыми инвариантами, для JPA-сущностей (нужны конструктор…

    Middle
  118. 118Что произойдёт, если объявить record с полем-массивом и сравнить два таких объекта с одинаковым содержимым массива?

    equals вернёт false: сгенерированный equals сравнивает компоненты их собственным equals, а у массива это сравнение по ссылке. hashCode тоже будет по идентичности, toString…

    Middle
  119. 119Какое главное преимущество даёт sealed-иерархия при использовании switch с pattern matching?

    Закрытый список наследников делает проверку полноты switch работой компилятора: не нужен default, а новый подтип — ошибка компиляции во всех switch, которые его не обрабатывают…

    Middle
  120. 120Что обязан сделать наследник sealed-класса?

    Наследник sealed-класса обязан: быть в permits (или в том же файле, если permits опущен), объявить себя final, sealed или non-sealed, лежать в том же модуле (вне модулей — в том…

    Middle
  121. 121Что даёт pattern matching в instanceof по сравнению с классической проверкой?

    Проверка и приведение объединяются: if (o instanceof String s) сразу даёт переменную s нужного типа. Нет дублирующего приведения, которое может разойтись с проверкой.

    Middle
  122. 122Почему встроенную Java-сериализацию считают небезопасной и устаревшей?

    Безопасность: десериализация сама создаёт объекты классов из потока и вызывает их методы восстановления до любой проверки — из классов в classpath собирают гаджет-цепочку и…

    Middle
  123. 123Что произойдёт с полем, помеченным transient, при сериализации и последующей десериализации?

    Поле не попадёт в поток, а после восстановления получит значение по умолчанию для типа (null, 0, false) — инициализатор поля и конструктор не выполняются.

    Middle
  124. 124Чем Externalizable отличается от Serializable?

    Externalizable — полный ручной контроль: формат пишут writeExternal и readExternal, нужен публичный конструктор без аргументов (вызывается при восстановлении). Serializable …

    Middle
  125. 125Что означают позиция, лимит и ёмкость у ByteBuffer, и что делает flip()?

    Ёмкость — размер буфера, позиция — курсор следующего чтения или записи, лимит — граница доступных данных. flip() ставит лимит на текущую позицию и обнуляет позицию — переключает…

    Middle
  126. 126Как виртуальные потоки изменили типичный выбор между блокирующим IO и неблокирующей моделью на Selector?

    Главный довод за event loop — дороговизна потока — снят: виртуальный поток дешёв и при блокировке отцепляется от несущего. Можно писать блокирующий читаемый код при высокой…

    Middle
  127. 127Что верно про JIT-компиляцию в HotSpot?

    Код сначала интерпретируется, горячие методы компилирует C1 (быстро, с профилированием), затем C2 (агрессивные оптимизации по профилю). Оптимизации спекулятивны: встраивание по…

    Middle
  128. 128Почему java.util.Stack, унаследованный от Vector, считают ошибкой дизайна?

    «Стек — это вектор» неверно: наследование выставило наружу get(i), add(i, x), remove(i) — операции, разрушающие инвариант LIFO. Правильно — композиция: список внутри, наружу…

    Middle
  129. 129Класс сделал все поля private и добавил к каждому геттер и сеттер. Достигнута ли инкапсуляция?

    Нет: инкапсуляция — это сокрытие состояния за операциями, которые держат инварианты. Сеттер на каждое поле позволяет привести объект в невозможное состояние: баланс отрицательный…

    Middle
  130. 130Что верно про полиморфизм в Java?

    Динамически (по реальному классу объекта) выбираются только переопределённые методы экземпляра. Статические методы скрываются, а не переопределяются: вызов определяется…

    Middle
  131. 131В каком порядке выполняется инициализация при создании объекта подкласса?

    Один раз при инициализации класса: static-поля и static-блоки — родитель, затем наследник. На каждый new: конструктор наследника сразу вызывает super(), отрабатывают поля и блоки…

    Middle
  132. 132Класс реализует два несвязанных интерфейса, в каждом из которых есть default-метод с одинаковой сигнатурой. Что произойдёт?

    Ошибка компиляции: класс обязан переопределить метод. Выбрать реализацию можно явно: A.super.method().

    Middle
  133. 133Ради чего в Java 8 добавили default-методы интерфейсов?

    Эволюция API без слома совместимости: добавление метода в интерфейс раньше ломало все реализации, а Collection и Iterable реализованы в бесчисленных библиотеках. Без default не…

    Middle
  134. 134Что верно про иерархию Throwable?

    Throwable → Error и Exception; RuntimeException — наследник Exception. Checked = Exception минус RuntimeException. Error (OutOfMemoryError, StackOverflowError) — среда в нерабочем…

    Middle
  135. 135Метод бросает исключение внутри try, а в блоке finally стоит return. Что получит вызывающий?

    Нормальный возврат: return в finally перекрывает исходный выход и проглатывает исключение — сбой бесследно исчезает. Так же действуют break и continue.

    Middle
  136. 136Почему вызов wait() принято помещать в цикл while, а не в if?

    Пробуждение не гарантирует, что условие выполнено: возможны ложные пробуждения (spurious wakeup), а между notify и захватом монитора другой поток мог снова изменить состояние…

    Middle
  137. 137На каких объектах не следует синхронизироваться?

    Не синхронизироваться на разделяемых или подменяемых объектах: строковых литералах (интернированы), Integer и других обёртках (кэш значений), публичном this, изменяемом поле…

    Middle
  138. 138Чем LongAdder выигрывает у AtomicLong при высокой конкуренции и в чём его ограничение?

    LongAdder разносит счёт по нескольким ячейкам: потоки не бьются за одну переменную, CAS не промахивается, кэш-линия не скачет между ядрами. Итог — сумма ячеек, а не мгновенно…

    Middle
  139. 139Какие возможности даёт ReentrantLock, недоступные при использовании synchronized?

    ReentrantLock добавляет tryLock (с таймаутом), lockInterruptibly, справедливый режим и несколько Condition. Цена — освобождение вручную: lock() перед try, unlock() в finally.

    Middle
  140. 140В parallel stream выполняется обращение к внешнему HTTP-сервису. Почему это опасно для всего приложения?

    Parallel stream выполняется в общем ForkJoinPool.commonPool — одном на JVM, размером «ядра − 1». Блокирующий HTTP-вызов занимает его потоки, и встают все parallel stream и…

    Middle
  141. 141В каких случаях parallel stream, скорее всего, не даст выигрыша или окажется медленнее последовательного?

    Выигрыша нет, когда мало данных или дешёвая операция (N × Q мало), источник плохо делится (LinkedList, Stream.iterate, итератор), есть сохранение порядка (forEachOrdered, limit…

    Middle
  142. 142Чем различаются exceptionally, handle и whenComplete у CompletableFuture?

    exceptionally — только при ошибке, подменяет результат. handle — вызывается всегда, получает значение и исключение и возвращает новый результат. whenComplete — побочный эффект…

    Middle
  143. 143Когда уместен CopyOnWriteArrayList?

    Каждая запись копирует весь массив — оправдано только при подавляющем преобладании чтений и небольшом размере: реестр слушателей, конфигурация.

    Middle
  144. 144Что верно про ёмкость и load factor в HashMap?

    Ёмкость — степень двойки (индекс через hash & (n-1) вместо остатка), при превышении ёмкость × 0.75 таблица удваивается, а цепочка становится деревом только при длине ≥ 8 и ёмкости…

    Middle
  145. 145Почему ArrayDeque не допускает null-элементов?

    null зарезервирован как сигнал «элемента нет»: poll и peek возвращают null для пустой очереди. Если бы null хранился, ответ стал бы неоднозначным.

    Middle
  146. 146Что верно про стек и кучу в JVM?

    Стек — у каждого потока свой (-Xss): кадры вызовов, локальные примитивы значением и ссылки. Куча — общая (-Xmx): сами объекты. Переполнение стека — StackOverflowError, нехватка…

    Middle
  147. 147Java-приложение запускают в контейнере с лимитом памяти. Как правильно задать размер кучи?

    Задавать кучу долей от лимита: -XX:MaxRAMPercentage=70–75, оставляя запас на память вне кучи (Metaspace, стеки, кодовый кэш, direct-буферы, GC). -Xmx, равный лимиту, приводит к…

    Middle
  148. 148Что невозможно из-за стирания типов?

    В рантайме параметра типа нет, поэтому нельзя: new T(), new T[n], instanceof List<String>, статическое поле типа T, перегрузка m(List<String>) и m(List<Integer>) (одинаковая…

    Middle
  149. 149Зачем в сигнатуре пишут <T extends Comparable<T>>?

    Граница сужает допустимые типы и открывает методы границы: без неё T — просто Object, и compareTo вызвать нельзя. После стирания T заменяется верхней границей — Comparable.

    Middle
  150. 150Чем опасно использование raw type, например List вместо List<String>?

    Raw type выключает проверку дженериков для всего выражения: в список строк можно положить число, а ClassCastException появится далеко — при чтении, где компилятор вставил…

    Middle
  151. 151Зачем в JDK помимо Function<T,R> существуют IntFunction, ToIntFunction и IntPredicate?

    Дженерики работают только со ссылочными типами, поэтому Function<Integer, Integer> упаковывает и распаковывает значения на каждом вызове. Специализации (IntFunction…

    Middle
  152. 152Переменной присвоили Stream, вызвали count(), а затем на той же переменной вызвали forEach(). Что произойдёт?

    IllegalStateException: stream has already been operated upon or closed. Стрим — одноразовый конвейер над источником, а не хранилище данных.

    Middle
  153. 153В конвейере стоят filter и map. Почему порядок filter перед map обычно предпочтительнее обратного?

    Элементы идут по конвейеру по одному: дорогое преобразование до фильтра выполняется и для отбрасываемых элементов. Чем раньше отсеять, тем меньше работы.

    Middle
  154. 154Функция значения в Collectors.toMap вернула null для одного из элементов. Что произойдёт?

    NullPointerException, хотя HashMap null-значения допускает: коллектор использует merge, а он по контракту запрещает null — не отличить от отсутствия ключа.

    Middle
  155. 155Чем orElse отличается от orElseGet?

    orElse(value) — аргумент вычисляется всегда, даже если значение есть (обычный порядок вычисления аргументов). orElseGet(supplier) — поставщик вызывается только при отсутствии.

    Middle
  156. 156Какие способы применения Optional считаются антипаттернами?

    Антипаттерны: Optional как поле (не сериализуем, лишняя аллокация), как параметр (перекладывает проблему на вызывающего), голый get() без проверки, isPresent + get вместо map и…

    Middle
  157. 157Статическое поле SimpleDateFormat используется из нескольких потоков, и изредка возвращаются неверные даты. В чём причина и что делать?

    SimpleDateFormat хранит изменяемый Calendar внутри: параллельные вызовы затирают состояние друг друга — неверные даты или исключения, причём только под нагрузкой. Замена …

    Middle
  158. 158Почему чтение файла по одному байту через FileInputStream радикально медленнее, чем через BufferedInputStream?

    Дорог не байт, а системный вызов с переходом в ядро. Чтение по байту из FileInputStream — по вызову на байт; BufferedInputStream читает блок (8 КБ) за один вызов и отдаёт байты из…

    Middle
  159. 159Приложение читает файл через new FileReader(path) без указания кодировки. Чем это опасно?

    Кодировка по умолчанию зависела от окружения (локаль ОС): одна сборка вела себя по-разному на машине разработчика и на сервере, данные молча портились. С Java 18 по умолчанию…

    Middle
  160. 160Почему в логировании предпочитают log.debug("user {} order {}", userId, orderId) вместо конкатенации строк?

    Отложенное форматирование: строка собирается, только если уровень включён. Конкатенация вычисляется до вызова всегда — на горячем пути с выключенным debug это лишние аллокации.

    Middle
  161. 161Что такое текстовый блок и как в нём работают отступы?

    Многострочный литерал в тройных кавычках: JSON, SQL, HTML без экранирования и конкатенации. Результат — обычная String. Общий отступ (по самой левой строке и закрывающим кавычкам)…

    Middle
  162. 162Что такое autoboxing и какие ловушки он приносит?

    Компилятор подставляет Integer.valueOf при упаковке и intValue при распаковке. Ловушки: == работает только внутри кэша −128…127, распаковка null — NPE, каждая упаковка вне кэша …

    Middle
  163. 163Как выбираешь структуру данных под задачу? Проведи рассуждение на примере: нужно хранить сессии пользователей с быстрым поиском по id и обходом в порядке добавления.

    Метод: какие операции горячие и как часто → сложность каждой у кандидатов → память и конкурентность. Поиск по id + обход в порядке добавления → LinkedHashMap; при доступе из…

    Middle
  164. 164В сервисе нужно сохранить момент оформления заказа и дату доставки, выбранную пользователем. Какие типы java.time возьмёшь и почему?

    Момент оформления — Instant (в БД timestamptz, всегда UTC): событие произошло объективно, его сравнивают и сортируют глобально. Дата доставки — LocalDate: это не момент, а выбор…

    Middle
  165. 165Два потока одновременно вызывают incrementAndGet() у одного AtomicInteger. Что при этом происходит внутри и почему ни один инкремент не теряется?

    CAS-цикл: прочитать значение, вычислить новое и записать, только если в памяти всё ещё старое (одна атомарная инструкция процессора). Проиграл гонку — повторить с новым значением…

    Middle
Партнёр платформы

Разбор собеседования с sotto

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

Разбор собеседования