🔍 Ответ на задачу про String.contains: Ловушка экранирования 🪤
Часто при переходе от регулярных выражений к обычным строковым методам в Java возникает путаница с экранированием.
Многие методы в Java (например,
Однако метод
В данном примере:
-
- Метод
- В строке
Вывод:
Результат будет
⚡️ Не перепутайте:
- Методы
- Методы
#java #string #contains #regex #backslash #интервью #java_interview_tasks
Часто при переходе от регулярных выражений к обычным строковым методам в Java возникает путаница с экранированием.
Многие методы в Java (например,
split, replaceAll) принимают регулярные выражения. В regex символ | (pipe) является специальным (логическое ИЛИ) и требует экранирования — \|.Однако метод
String.contains(CharSequence s) ищет буквальное совпадение подстроки.В данном примере:
-
MULTIPLE_VALUES_SPLITTER инициализируется строкой \| (обратный слеш и вертикальная черта).- Метод
contains честно ищет эти два символа подряд.- В строке
"apple|orange|banana" есть только символ |, но нет символа \.Вывод:
Результат будет
false. Для корректной проверки наличия разделителя в данном случае нужно использовать val.contains("|").⚡️ Не перепутайте:
- Методы
contains, indexOf, replace работают с литералами.- Методы
split, replaceAll, matches работают с регулярными выражениями.#java #string #contains #regex #backslash #интервью #java_interview_tasks
👍8❤1🔥1
🔍 Ответ на задачу про Double.NaN: 👻
- Согласно стандарту IEEE 754,
- Однако
Вывод:
Сравнение примитивов даст
⚡️ Не перепутайте:
Для проверки на
#java #double #nan #floatingpoint #интервью #java_interview_tasks
- Согласно стандарту IEEE 754,
NaN не равен самому себе. Поэтому x == y всегда false.- Однако
Double.equals() реализован так, что он считает два NaN равными. Это сделано для того, чтобы NaN можно было использовать в коллекциях (например, как ключ в HashMap).Вывод:
Сравнение примитивов даст
false, а объектов — true.⚡️ Не перепутайте:
Для проверки на
NaN у примитивов используйте Double.isNaN(x).#java #double #nan #floatingpoint #интервью #java_interview_tasks
👍7🔥1
🔍 Ответ на задачу про HashSet: Опасность мутабельных объектов 🧩
Когда мы положили
Вывод:
⚡️ Не перепутайте:
Никогда не используйте изменяемые (mutable) поля в
#java #collections #hashset #hashcode #bug #интервью #java_interview_tasks
Когда мы положили
p в сет, он попал в "корзину" (bucket), соответствующую hashCode = 1. После изменения p.x = 2, hashCode объекта тоже стал равен 2. Когда мы вызываем contains(p), сет ищет объект в корзине №2, но наш объект всё еще лежит в корзине №1! Сет его не найдет.Вывод:
contains вернет false, но размер сета по-прежнему 1. Объект "застрял" в неправильной корзине.⚡️ Не перепутайте:
Никогда не используйте изменяемые (mutable) поля в
hashCode и equals, если объекты будут храниться в сетах или мапах.#java #collections #hashset #hashcode #bug #интервью #java_interview_tasks
👍6🔥2👏1
🔍 Ответ на задачу про Integer.MIN_VALUE: Математические странности 🧮
Диапазон
Вывод:
Оба условия выведут
⚡️ Не перепутайте:
Всегда помните об асимметрии диапазона целых чисел в Java. Это частый источник багов при использовании
#java #int #overflow #math #basics #интервью #java_interview_tasks
Диапазон
int в Java — от -2,147,483,648 до 2,147,483,647. Заметьте, что отрицательных чисел на одно больше. При попытке вычислить -Integer.MIN_VALUE происходит переполнение, и число превращается... снова в Integer.MIN_VALUE!Вывод:
Оба условия выведут
true. Отрицание минимального значения int дает то же самое отрицательное число.⚡️ Не перепутайте:
Всегда помните об асимметрии диапазона целых чисел в Java. Это частый источник багов при использовании
Math.abs().#java #int #overflow #math #basics #интервью #java_interview_tasks
❤7🔥2💯1👀1
🔍 Ответ на задачу про IdentityHashMap: Когда ссылки важнее значений 🔗
-
-
Вывод:
Размер мапы будет 2.
⚡️ Не перепутайте:
#java #collections #hashmap #identityhashmap #internals #интервью #java_interview_tasks
-
HashMap использует equals() и hashCode() для сравнения ключей. Для "Java" и new String("Java") equals вернет true, поэтому в HashMap была бы 1 запись.-
IdentityHashMap использует оператор ==. Так как s1 и s2 — это разные объекты в памяти, мапа считает их разными ключами.Вывод:
Размер мапы будет 2.
⚡️ Не перепутайте:
IdentityHashMap — редкий зверь. Она полезна, например, при сериализации графа объектов, чтобы не зациклиться, если два узла имеют одинаковое содержимое, но являются разными объектами.#java #collections #hashmap #identityhashmap #internals #интервью #java_interview_tasks
🔥6👏2👍1
🔍 Ответ на задачу про Enum.values(): Скрытые аллокации 📦
Спецификация Java требует, чтобы массив, возвращаемый
Вывод:
Каждый вызов
⚡️ Не перепутайте:
Если вам нужно просто получить количество элементов, используйте кешированное значение или Java 21
#java #enum #performance #jvm #memory #интервью #java_interview_tasks
Спецификация Java требует, чтобы массив, возвращаемый
values(), был изменяемым (вы можете заменить в нем элементы, хотя это и плохая практика). Чтобы пользователи не могли испортить внутреннее состояние перечисления, компилятор генерирует код, который создает копию массива при каждом вызове values().Вывод:
Каждый вызов
values() — это новая аллокация памяти. В высокопроизводительном коде лучше кешировать этот массив: private static final Color[] VALUES = Color.values().⚡️ Не перепутайте:
Если вам нужно просто получить количество элементов, используйте кешированное значение или Java 21
Enum.entries.#java #enum #performance #jvm #memory #интервью #java_interview_tasks
👍7🔥1
🔍 Ответ на задачу про Iterator.remove(): Чистим коллекцию правильно 🧹
- Вариант A (for-each) использует итератор неявно. Если мы вызываем
- Вариант B использует
Вывод:
Верный вариант — B. (Хотя есть исключение: в ArrayList удаление предпоследнего элемента через
⚡️ Не перепутайте:
В Java 8+ самый простой и безопасный способ:
#java #collections #iterator #bug #clean_code #интервью #java_interview_tasks
- Вариант A (for-each) использует итератор неявно. Если мы вызываем
list.remove() напрямую, итератор об этом не знает и при следующей проверке modCount выбросит ConcurrentModificationException.- Вариант B использует
iterator.remove(). Этот метод специально спроектирован для безопасного удаления текущего элемента во время итерации.Вывод:
Верный вариант — B. (Хотя есть исключение: в ArrayList удаление предпоследнего элемента через
list.remove() в for-each может не вызвать ошибку из-за бага/особенности проверки hasNext(), но полагаться на это нельзя).⚡️ Не перепутайте:
В Java 8+ самый простой и безопасный способ:
list.removeIf(s -> s.equals("A")).#java #collections #iterator #bug #clean_code #интервью #java_interview_tasks
Telegram
Java Interview Tasks
Можно ли удалять элементы из списка во время обхода?
Какой код НЕ выбросит ConcurrentModificationException?
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
// Вариант A
for (String s : list) {
if (s.equals("A")) list.remove(s);…
Какой код НЕ выбросит ConcurrentModificationException?
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
// Вариант A
for (String s : list) {
if (s.equals("A")) list.remove(s);…
👏5❤1🍌1
🔍 Ответ на задачу про LinkedHashMap: Порядок имеет значение 🔄
У
Вывод:
Так как мы обратились к ключу
⚡️ Не перепутайте:
По умолчанию
#java #collections #linkedhashmap #lru #cache #интервью #java_interview_tasks
У
LinkedHashMap есть специальный конструктор, где третий аргумент accessOrder включает режим "порядка доступа". Если он равен true, то при каждом get() или put() элемент перемещается в конец списка. Это идеальная основа для реализации LRU-кеша (Least Recently Used).Вывод:
Так как мы обратились к ключу
2, он переместился в конец. Порядок станет: 1, 3, 2.⚡️ Не перепутайте:
По умолчанию
LinkedHashMap сохраняет порядок вставки (accessOrder = false).#java #collections #linkedhashmap #lru #cache #интервью #java_interview_tasks
🔥8👍2👏1
🔍 Ответ на задачу про Наследование: Приватные методы не переопределяются 🛡
Приватные методы в Java не участвуют в полиморфизме. Они принадлежат только тому классу, в котором объявлены, и не могут быть переопределены (override). Когда метод
Вывод:
Напечатается "Parent". Метод
⚡️ Не перепутайте:
Если вы хотите, чтобы метод переопределялся, он должен быть как минимум
#java #oop #inheritance #polymorphism #basics #интервью #java_interview_tasks
Приватные методы в Java не участвуют в полиморфизме. Они принадлежат только тому классу, в котором объявлены, и не могут быть переопределены (override). Когда метод
test() вызывается у объекта Child, он ищется в Parent. Внутри test() вызывается print(), который в Parent помечен как private. Java связывает этот вызов статически именно с методом в Parent.Вывод:
Напечатается "Parent". Метод
print() в Child — это просто новый метод, который никак не связан с приватным методом родителя.⚡️ Не перепутайте:
Если вы хотите, чтобы метод переопределялся, он должен быть как минимум
protected.#java #oop #inheritance #polymorphism #basics #интервью #java_interview_tasks
❤5👍3
🔍 Ответ на задачу про Static:
Статические методы привязаны к классу, а не к объекту. В Java нет полиморфизма для статики. Это называется method hiding. Какой метод вызовется, определяется типом переменной во время компиляции, а не типом объекта во время выполнения.
Вывод:
Так как переменная
⚡️ Не перепутайте:
Никогда не вызывайте статические методы через экземпляры объектов (
#java #static #inheritance #basics #clean_code #интервью #java_interview_tasks
Статические методы привязаны к классу, а не к объекту. В Java нет полиморфизма для статики. Это называется method hiding. Какой метод вызовется, определяется типом переменной во время компиляции, а не типом объекта во время выполнения.
Вывод:
Так как переменная
obj имеет тип A, вызовется A.staticMethod(). Результат: "A".⚡️ Не перепутайте:
Никогда не вызывайте статические методы через экземпляры объектов (
obj.method()). Всегда пишите ClassName.method(), чтобы не вводить в заблуждение.#java #static #inheritance #basics #clean_code #интервью #java_interview_tasks
🔥6👍2🤔1
🔍 Ответ на задачу про Final поля: Безопасная публикация 🏗
Согласно JMM, поля
Вывод:
При условии отсутствия "утечки"
⚡️ Не перепутайте:
Обычные (не
#java #concurrency #jmm #final #multithreading #интервью #java_interview_tasks
Согласно JMM, поля
final обеспечивают "гарантию заморозки". Если объект был правильно сконструирован (ссылка this не утекла во время работы конструктора), то любой поток, увидевший ссылку на этот объект, гарантированно увидит корректные значения всех его final полей.Вывод:
При условии отсутствия "утечки"
this в конструкторе , после создания объекта другой тред увидеть не может ничего кроме 5. Это одна из основ создания Immutable объектов в Java.⚡️ Не перепутайте:
Обычные (не
final) поля без синхронизации могут быть видны другим потокам в их дефолтном состоянии (например, 0 или null), даже если конструктор уже отработал.#java #concurrency #jmm #final #multithreading #интервью #java_interview_tasks
🔥4
🔍 Ответ на задачу про Generics: Стирание типов (Type Erasure) 🧼
В Java дженерики реализованы через стирание типов. Это сделано для обратной совместимости с кодом до Java 5. Во время компиляции проверки проводятся, но в байт-коде вся информация о типах
Вывод:
Оба списка принадлежат одному и тому же классу
⚡️ Не перепутайте:
Из-за стирания типов вы не можете сделать
#java #generics #jvm #internals #basics #интервью #java_interview_tasks
В Java дженерики реализованы через стирание типов. Это сделано для обратной совместимости с кодом до Java 5. Во время компиляции проверки проводятся, но в байт-коде вся информация о типах
<String> и <Integer> удаляется, и оба списка превращаются в просто ArrayList (работающий с Object).Вывод:
Оба списка принадлежат одному и тому же классу
java.util.ArrayList. Результат: true.⚡️ Не перепутайте:
Из-за стирания типов вы не можете сделать
instanceof List<String> или создать массив дженериков new T[10].#java #generics #jvm #internals #basics #интервью #java_interview_tasks
👌5👍1👏1
🔍 Ответ на задачу про Wildcards: List<Object> vs List<?> ❓
1.
2.
3. В
Вывод:
Не скомпилируются строки 1 и 3.
⚡️ Не перепутайте:
#java #generics #wildcards #basics #интервью #java_interview_tasks
1.
List<Object> не является родителем для List<String>. Несмотря на то, что String — это Object, сами коллекции инвариантны. Иначе мы могли бы положить Integer в список строк через ссылку на List<Object>.2.
List<?> (wildcard) — это родитель для любого List. Строка 2 верна.3. В
List<?> нельзя ничего добавлять (кроме null), так как мы не знаем, список какого типа там на самом деле.Вывод:
Не скомпилируются строки 1 и 3.
⚡️ Не перепутайте:
List<Object> — это список, в который можно класть любые объекты.List<?> — это список какого-то неизвестного типа, из него можно только читать.#java #generics #wildcards #basics #интервью #java_interview_tasks
✍6👍4👏1
🔍 Ответ на задачу про PECS: Producer Extends, Consumer Super 🦆
Это правило PECS:
- Producer Extends: Если коллекция "производит" данные (мы из нее читаем), используйте
- Consumer Super: Если коллекция "потребляет" данные (мы в нее пишем), используйте
Вывод:
Верна только строка A.
⚡️ Не перепутайте:
#java #generics #pecs #clean_code #интервью #java_interview_tasks
Это правило PECS:
- Producer Extends: Если коллекция "производит" данные (мы из нее читаем), используйте
extends. Мы гарантируем, что там лежат объекты типа T или его наследники, поэтому их безопасно приводить к T.- Consumer Super: Если коллекция "потребляет" данные (мы в нее пишем), используйте
super. Мы можем безопасно положить туда T. Но при чтении мы получим только Object, так как не знаем реального типа.Вывод:
Верна только строка A.
⚡️ Не перепутайте:
List<? extends T> — только для чтения.List<? super T> — в основном для записи.#java #generics #pecs #clean_code #интервью #java_interview_tasks
🔥5
### 🧮 Задача: (7x−y)(7y−z)(7z−x) = 11, где x, y, z — целые числа
### Решение: 🚫
Ключевое наблюдение — посмотрим на чётность произведения
Сложим все три множителя:
Сумма трёх множителей всегда чётна (кратна 6). Если сумма трёх целых чисел чётна, то среди них либо все три чётные, либо ровно два нечётных и одно чётное. В обоих случаях хотя бы один множитель — чётный. А значит, произведение
Но 11 — нечётное число.
### Вывод:
Уравнение не имеет решений в целых числах.
#math #numbertheory #diophantine #интервью #java_interview_tasks
### Решение: 🚫
Ключевое наблюдение — посмотрим на чётность произведения
(7x−y)(7y−z)(7z−x).Сложим все три множителя:
(7x − y) + (7y − z) + (7z − x) = 6x + 6y + 6z = 6(x + y + z)Сумма трёх множителей всегда чётна (кратна 6). Если сумма трёх целых чисел чётна, то среди них либо все три чётные, либо ровно два нечётных и одно чётное. В обоих случаях хотя бы один множитель — чётный. А значит, произведение
(7x−y)(7y−z)(7z−x) всегда чётно при любых целых x, y, z.Но 11 — нечётное число.
### Вывод:
Уравнение не имеет решений в целых числах.
#math #numbertheory #diophantine #интервью #java_interview_tasks
🤔6👍3🔥2
🔍 Ответ на задачу про Method References: Неоднозначность 😵💫
Ссылка
1. Как вызов статического метода:
2. Как вызов обычного метода у текущего элемента:
Обе интерпретации идеально подходят под сигнатуру
Вывод:
Возникает ошибка компиляции из-за неоднозначности.
⚡️ Не перепутайте:
В таких случаях используйте обычную лямбду
#java #lambda #methodreference #bug #интервью #java_interview_tasks
Ссылка
Service::process может быть интерпретирована двумя способами:1. Как вызов статического метода:
(Service s) -> Service.process(s).2. Как вызов обычного метода у текущего элемента:
(Service s) -> s.process().Обе интерпретации идеально подходят под сигнатуру
Consumer<Service>, который ожидает forEach. Компилятор не знает, какой метод выбрать.Вывод:
Возникает ошибка компиляции из-за неоднозначности.
⚡️ Не перепутайте:
В таких случаях используйте обычную лямбду
s -> s.process(), чтобы явно указать нужный метод.#java #lambda #methodreference #bug #интервью #java_interview_tasks
🔥5👍2👌1
🔍 Ответ на задачу про Stream.findFirst vs findAny: В чём разница? 🔍
-
-
Вывод:
В параллельном стриме
⚡️ Не перепутайте:
В последовательном (sequential) стриме
#java #streamapi #parallel #performance #интервью #java_interview_tasks
-
findFirst() жестко привязан к порядку следования (encounter order). В параллельном стриме он потратит время на то, чтобы убедиться, что вернул именно первый элемент.-
findAny() позволяет среде выполнения выбрать любой подходящий элемент. В параллельных стримах это работает гораздо быстрее, так как не нужно координировать потоки для соблюдения порядка.Вывод:
В параллельном стриме
findAny() может вернуть любой элемент, подходящий под условие. Если порядок не важен — используйте его для скорости.⚡️ Не перепутайте:
В последовательном (sequential) стриме
findAny() чаще всего тоже будет возвращать первый элемент, но спецификация этого не гарантирует.#java #streamapi #parallel #performance #интервью #java_interview_tasks
👍6🔥1
🔍 Ответ на задачу про Stream.flatMap:
-
-
Вывод:
Вместо двух вложенных списков мы получим один стрим из 3-х символов: "a", "b", "c". Результат
⚡️ Не перепутайте:
Используйте
#java #streamapi #flatmap #basics #интервью #java_interview_tasks
-
map() превращает каждый элемент в другой элемент (1 -> 1). Если применить его здесь, мы получим стрим стримов: Stream<Stream<String>>.-
flatMap() превращает каждый элемент в стрим, а затем "склеивает" все эти стримы в один плоский Stream<String>.Вывод:
Вместо двух вложенных списков мы получим один стрим из 3-х символов: "a", "b", "c". Результат
count() — 3.⚡️ Не перепутайте:
Используйте
flatMap, когда ваш объект содержит коллекцию или Optional, и вы хотите работать с их содержимым напрямую.#java #streamapi #flatmap #basics #интервью #java_interview_tasks
🔥2👌1
🔍 Ответ на задачу про Stream.reduce: Опасность
Первый аргумент
Вычисление идет так:
В нашем случае:
Вывод:
Напечатается 16. Если вы хотите просто сумму — identity должен быть 0. Если произведение — 1.
⚡️ Не перепутайте:
Identity должен быть нейтральным элементом для вашей операции. Для сложения это 0, для умножения 1, для конкатенации строк — пустая строка.
#java #streamapi #reduce #basics #интервью #java_interview_tasks
identity 🚩Первый аргумент
reduce — это identity. Это значение, которое возвращается, если стрим пуст, и которое используется как начальное при вычислении.Вычисление идет так:
identity + element1 + element2...В нашем случае:
10 + 1 + 2 + 3 = 16.Вывод:
Напечатается 16. Если вы хотите просто сумму — identity должен быть 0. Если произведение — 1.
⚡️ Не перепутайте:
Identity должен быть нейтральным элементом для вашей операции. Для сложения это 0, для умножения 1, для конкатенации строк — пустая строка.
#java #streamapi #reduce #basics #интервью #java_interview_tasks
👍5❤1👌1
🔍 Ответ на задачу про LocalDate: Ловушка иммутабельности 📅
Классы из пакета
Вывод:
Напечатается 1. Чтобы получить 11, нужно было написать
⚡️ Не перепутайте:
Всегда проверяйте, что вы используете возвращаемое значение методов
#java #datetime #immutable #bug #basics #интервью #java_interview_tasks
Классы из пакета
java.time (LocalDate, LocalTime, etc.) — immutable (неизменяемые), как и String. Любой метод, который якобы "меняет" объект, на самом деле возвращает новый объект с измененным состоянием. Исходный объект date остается прежним.Вывод:
Напечатается 1. Чтобы получить 11, нужно было написать
date = date.plusDays(10).⚡️ Не перепутайте:
Всегда проверяйте, что вы используете возвращаемое значение методов
java.time. Это одна из самых частых ошибок при переходе со старого Calendar.#java #datetime #immutable #bug #basics #интервью #java_interview_tasks
🔥6👏2❤1👍1