en
Feedback
Библиотека собеса по Java | вопросы с собеседований

Библиотека собеса по Java | вопросы с собеседований

Open in Telegram

Вопросы с собеседований по Java и ответы на них. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/08c603b6 Для обратной связи: @proglibrary_feeedback_bot

Show more
6 485
Subscribers
+124 hours
+87 days
+1330 days
Posts Archive
Как работает HashMap внутри? Что происходит при коллизии и при достижении load factor? HashMap — массив бакетов (Node[] table). Ключ хешируется, хеш определяет индекс бакета: index = hash & (capacity - 1 Что происходит при put(key, value): Считается hash(key) — не просто hashCode(), а с дополнительным перемешиванием старших битов ((h = key.hashCode()) ^ (h >>> 16)). Это снижает коллизии при маленьком размере таблицы. Находится бакет по индексу. Если пустой — кладём первым. Если нет — коллизия. 🔹 Коллизия: До Java 8 → связный список в бакете. Поиск O(n) в худшем случае. С Java 8 → когда в бакете больше 8 элементов и capacity >= 64, список превращается в красно-чёрное дерево. Поиск становится O(log n). Обратно в список — при сжатии ниже 6 элементов.
// Упрощённо: Node в списке или TreeNode в дереве
static class Node<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}
🔹 Load factor и resize: По умолчанию capacity = 16, loadFactor = 0.75. Порог = capacity * loadFactor = 12. Как только элементов стало больше 12 — начинается resize(): таблица удваивается до 32, все элементы перераспределяются по новым бакетам. Это O(n) операция. Поэтому если заранее знаете размер — задавайте начальную ёмкость:
// Хотим 1000 элементов без resize:
// 1000 / 0.75 ≈ 1334, берём следующую степень двойки
Map<String, Integer> map = new HashMap<>(2048);
🐸 Библиотека собеса по Java #core

Как работает HashMap внутри? Что происходит при коллизии и при достижении load factor? HashMap — массив бакетов (Node[] table). Ключ хешируется, хеш определяет индекс бакета: index = hash & (capacity - 1 Что происходит при put(key, value): Считается hash(key) — не просто hashCode(), а с дополнительным перемешиванием старших битов ((h = key.hashCode()) ^ (h >>> 16)). Это снижает коллизии при маленьком размере таблицы. Находится бакет по индексу. Если пустой — кладём первым. Если нет — коллизия. 🔹 Коллизия: До Java 8 → связный список в бакете. Поиск O(n) в худшем случае. С Java 8 → когда в бакете больше 8 элементов и capacity >= 64, список превращается в красно-чёрное дерево. Поиск становится O(log n). Обратно в список — при сжатии ниже 6 элементов.
// Упрощённо: Node в списке или TreeNode в дереве
static class Node<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}
🔹 Load factor и resize: По умолчанию capacity = 16, loadFactor = 0.75. Порог = capacity * loadFactor = 12. Как только элементов стало больше 12 — начинается resize(): таблица удваивается до 32, все элементы перераспределяются по новым бакетам. Это O(n) операция. Поэтому если заранее знаете размер — задавайте начальную ёмкость:
// Хотим 1000 элементов без resize:
// 1000 / 0.75 ≈ 1334, берём следующую степень двойки
Map<String, Integer> map = new HashMap<>(2048);
🐸 Библиотека собеса по Java #core

✔️ Java-тест: кэш, который врёт Метод возвращает устаревшие данные. Иногда и только на нескольких потоках. Воспроизвести локально — нереально 👇 📦 Задание — code review Команда добавила простой in-memory кэш для тяжёлых вычислений. На одном потоке работает идеально. На проде с нагрузкой — иногда возвращает старый результат или null.
@Component
public class PricingCache {

    private final Map<String, BigDecimal> cache = new HashMap<>();
    private final PricingEngine pricingEngine;

    public PricingCache(PricingEngine pricingEngine) {
        this.pricingEngine = pricingEngine;
    }

    public BigDecimal getPrice(String productId) {
        if (cache.containsKey(productId)) {
            return cache.get(productId);
        }
        BigDecimal price = pricingEngine.calculate(productId);
        cache.put(productId, price);
        return price;
    }

    public void invalidate(String productId) {
        cache.remove(productId);
    }

    public void invalidateAll() {
        cache.clear();
    }
}
▪️ Объясни — В чём проблема в коде — Как переписать getPrice верно Ставьте → 🔥, если нравится формат. Если нет → 🌚 💬 Решения под спойлер. Сравним, какое будет лучше. 🐸 Библиотека собеса по Java #practise

Чем отличается ReentrantLock от synchronized? 🔹 synchronized — встроенный монитор JVM. Прост, но ограничен: — нельзя прервать ожиданиенет tryLockнельзя узнать, занят ли монитор 🔹 ReentrantLock из java.util.concurrent.locks — явная блокировка с расширенными возможностями:
ReentrantLock lock = new ReentrantLock();

// Попытка без ожидания
if (lock.tryLock()) {
    try {
        // критическая секция
    } finally {
        lock.unlock(); // обязателен!
    }
}

// С таймаутом
if (lock.tryLock(500, TimeUnit.MILLISECONDS)) { ... }

// С прерыванием
lock.lockInterruptibly();
🔹 Когда synchronized Простые сценарии, нет нужды в доп. функциях, меньше кода и риска ошибок. 🔹 Когда ReentrantLock Нужен tryLock, таймаут, прерывание, несколько Condition, или fairness. 🐸 Библиотека собеса по Java #concurrency

Для чего нужен @Conditional в Spring? @Conditional регистрирует бин только при выполнении определённого условия.
@Bean
@Conditional(WindowsCondition.class)
public Service windowsService() {
    return new WindowsService();
}

class WindowsCondition implements Condition {
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        return System.getProperty("os.name")
            .contains("Windows");
    }
}
Spring Boot предоставляет готовые: @ConditionalOnProperty, @ConditionalOnClass, @ConditionalOnMissingBean. 🐸 Библиотека собеса по Java #spring

Осталось всего 4 места на курс по ИИ-агентам. 30 апреля закрываем набор окончательно. В ГС честно рассказали: — Кому курс не подойдет; — Какой хардкор в программе (LangGraph, AutoGen, CrewAI); — Как мы даем токены, чтобы вы не тратили свои деньги. 🏃‍♀️ Записаться, пока есть места

В чем разница между параллелизмом и многопоточностью? Многопоточность — это способность программы выполнять несколько потоков , где каждый поток может выполняться независимо, но не обязательно одновременно. Потоки могут переключаться между собой, создавая иллюзию одновременности, однако они могут работать на одном ядре процессора. Параллелизм, с другой стороны, — это выполнение нескольких задач одновременно, обычно на разных процессорах или ядрах. В контексте параллелизма, задачи действительно выполняются одновременно. 🐸 Библиотека собеса по Java #concurrency

Что такое иммутабельный объект? Иммутабельный объект — это объект, состояние которого невозможно изменить после его создания.  Иммутабельность способствует безопасности потоков и предотвращению ошибок, связанных с изменениями состояния объектов. Примером может служить класс String. 🐸 Библиотека собеса по Java #core

🏃‍♀️ Как провести вечер вторника с пользой для карьеры? Включайте кружок там личное приглашение от спикера. 👆 Уже завтра в прямом эфире, разбираем архитектуру контекста в мультиагентных системах. 🤫 Секретный лут: промик на 5.000₽. Он достанется только тем, кто придет на прямой эфир. 👉 Регистрируйтесь на трансляцию

Что такое WeakReference? WeakReference — это слабая ссылка на объект, которая не препятствует его удалению сборщиком мусора. Если на объект есть только weak references, GC может удалить его при нехватке памяти.
WeakReference<Data> weak = new WeakReference<>(data);
data = null; 
// GC может удалить объект
Data retrieved = weak.get(); // может вернуть null
Используется в кешах (WeakHashMap), где элементы могут быть удалены при нехватке памяти, или для предотвращения memory leaks в listeners. 🐸 Библиотека собеса по Java #jvm

Что такое Phantom Reference? PhantomReference — самая слабая ссылка в Java. Отличается от WeakReference тем, что get() всегда возвращает null. Используется для отслеживания момента, когда объект удалён из памяти. После удаления объекта PhantomReference помещается в ReferenceQueue. В отличие от finalize(), это надёжный способ отследить удаление объекта. Используется редко, в основном во внутренних механизмах или для управления off-heap памятью. 🐸 Библиотека собеса по Java #jvm

Как работает G1 GC? G1 делит heap на равные регионы (~2048 штук) вместо фиксированных Young/Old/Perm зон. Каждый регион динамически назначается как Eden, Survivor или Old. Ключевые фазы Initial Mark — STW, помечает GC rootsConcurrent Mark — параллельно с приложением строит граф достижимостиRemark — STW, дочищает concurrent-фазу (SATB-алгоритм)Cleanup / Evacuation — копирует живые объекты из регионов с наибольшим мусором (отсюда "Garbage First") 🐸 Библиотека собеса по Java #core

Что такое Optional и когда его НЕ стоит использовать? Optional<T> — контейнер, который явно сигнализирует об отсутствии значения вместо null. Не стоит использоватьВ полях класса (не сериализуется хорошо)В параметрах методов (лучше перегрузка)В Collections (List<Optional<T>> — антипаттерн) Стоит использовать: как возвращаемый тип, когда значение действительно может отсутствовать. 🐸 Библиотека собеса по Java #core

Что такое false sharing в многопоточности и как его избежать? False sharing возникает, когда разные потоки обновляют разные переменные, находящиеся в одной кэш-линии CPU. Несмотря на отсутствие логической связи, процессор вынужден постоянно инвалидировать кэш, создавая задержки. Последствия: высокая латентность, падение пропускной способности, резкое ухудшение производительности в hot-paths. Как избежать:Разнести горячие поля по разным кэш-линиям → использовать @Contended (JDK 8+, требует -XX:-RestrictContended).Заполнять структуру “паддингом” вручную.Перепроектировать алгоритм, чтобы снизить частоту записи. 🐸 Библиотека собеса по Java #concurrency

Чем BeanFactory отличается от ApplicationContext? BeanFactory — минималистичный IoC-контейнер. Умеет создавать бины и резолвить зависимости. Бины создаются лениво — только при первом getBean(). Используется в очень ресурсоограниченных средах (embedded-системы), в обычных Spring-приложениях практически не встречается. ApplicationContext расширяет BeanFactory и добавляет всё, без чего реальное приложение не живёт: eager-инициализацию singleton'ов при старте, поддержку событий (ApplicationEvent), интернационализацию (MessageSource), lifecycle-коллбэки (@PostConstruct / @PreDestroy), AOP-интеграцию и работу с окружением (Environment / @Value). ⚠️ ApplicationContext создаёт все singleton-бины сразу при старте. Это значит: ошибки конфигурации (неверные зависимости, битые @Value) падают немедленно, а не при первом обращении к бину в рантайме. 🐸 Библиотека собеса по Java #spring

🏃‍♀️ Мы собрали бесплатный мега-гайд по ии-агентам 👇 В первой части постов навалили жесткой базы, чтобы вправить мозги на м
🏃‍♀️ Мы собрали бесплатный мега-гайд по ии-агентам 👇 В первой части постов навалили жесткой базы, чтобы вправить мозги на место. Во второй дали конкретные инструменты, фреймворки и пошаговые инструкции, что нужно кодить прямо сейчас. Часть 1. Введение, юзкейсы и реальность Разбираемся с терминами, снимаем розовые очки и смотрим, где ИИ реально приносит бабки, а где только жжет нервы: 1. «Так что вообще считается AI-агентом?» 2. «Где тут бот, а где уже AI-агент?» 3. «Не надо пихать AI-агента в каждую задачу» 4. «Что уже можно спокойно делать через AI-агентов?» 5. «А что через AI-агентов пока лучше не трогать?» Часть 2. Изнанка, ошибки и архитектура Как всё это устроено под капотом, чтобы не слить бюджет и не наломать дров на старте: 6. «Можно ли просто сесть вечером и собрать себе AI-агента?» 7. «С чего вообще начать, если хочется попробовать AI-агентов» 8. «Почему AI-агент может внезапно начать творить дичь» 9. «Где AI-агенты реально экономят время, а где только добавляют возни» 10. «Почему они жрут столько денег?» Часть 3. Хардкорная практика (Что делать руками) Хватит теории. Открываем ноут, запускаем Cursor и делаем нормальные, отказоустойчивые системы: 11. «Почему одного промпта мало?» 12. «Почему AI-агенту мало просто “дать доступ к данным”» 13. «Если не следить за AI-агентом, он быстро начинает жить своей жизнью» 14. «Собрать демку легко. Но как же сделать нормально» 15. «Как сделать, чтобы это не развалилось через неделю?» 👍 Сохраняйте пост в избранное, чтобы не потерять. 🤫 А завтра стартует наш курс по ии-агентам

💬 Обратная связь Ежемесячный опрос по грейдам. Сколько среди нас джедаев мидлов? Ваш грейд: 🔥 — Senior 👍🏼 — Middle ❤️ — Junior 😁 — Ещё учусь 🐸 Библиотека собеса по Java

✔️ Java-тест: бин-синглтон, который не синглтон Работает у одного — сломано у другого. В логах — каша из чужих данных 👇 📦 Задание — code review Команда добавила контекст текущего пользователя в сервис через поле. Локально — всё ок. На проде с несколькими потоками — пользователи видят чужие данные.
@Service
public class ReportService {

    private User currentUser;
    private ReportFilter activeFilter;

    private final ReportRepository reportRepository;

    public ReportService(ReportRepository reportRepository) {
        this.reportRepository = reportRepository;
    }

    public void initContext(User user, ReportFilter filter) {
        this.currentUser = user;
        this.activeFilter = filter;
    }

    public List<Report> getReports() {
        if (currentUser == null) {
            throw new IllegalStateException("Context not initialized");
        }

        return reportRepository.findByUserAndFilter(
            currentUser.getId(),
            activeFilter
        );
    }

    public ReportSummary getSummary() {
        List<Report> reports = getReports();
        return ReportSummary.calculate(reports, currentUser);
    }
}
▪️ Объясни — Какой скоуп у бина по умолчанию в Spring и почему это делает поля-состояния опасными. — Почему synchronized над методами не является правильным решением здесь. — Как переписать код, чтобы работало. Ставьте → 🔥, если нравится формат. Если нет → 🌚 💬 Решения под спойлер. Сравним, какое будет лучше. 🐸 Библиотека собеса по Java #practise

Можно ли изменить значение final переменной через рефлексию? Технически можно, но это нарушает контракт final и приводит к непредсказуемому поведению.
Field field = obj.getClass().getDeclaredField("finalField");
field.setAccessible(true);
field.set(obj, newValue);  // может не сработать
ПроблемыJVM может заинлайнить final значение при компиляцииизменения могут не отразиться из-за оптимизацийнарушается thread-safety гарантия final 🐸 Библиотека собеса по Java #core