Java Learning
18.7K subscribers
1.62K photos
1 video
3 files
998 links
№ 5079899194

Обучающий канал по Java

Ссылка для друга - https://t.iss.one/+ZEYYht6-46w5MDM6

По всем вопросам @mascarov_valentin

Реклама на бирже - https://telega.in/c/Java_per_month
Download Telegram
#Вопросы_с_собеседования
Объясните принципы работы и применение «стримов» (streams) в Java. Какие операции можно выполнять с использованием стримов? Приведите пример кода с использованием стримов.


Ответ:

Стримы представляют собой последовательность элементов, которую можно обрабатывать функциональными операциями. Стримы применяют в фильтрации для выборки элементов, для отображения (Mapping), сортировки и свертки (Reduction).

Объяснение кода:


words.stream(): Создание стрима из списка слов.
.filter(word -> word.length() > 5): Фильтрация слов, оставляя только те, у которых длина больше 5 символов.
.map(String::toUpperCase): Преобразование каждого слова в верхний регистр.
.sorted(): Сортировка слов.
.collect(Collectors.toList()): Сбор результатов в список.
Результат выводится на экран: [BANANA, ORANGE].
👍20
TimeUnit

TimeUnit — этоперечисление (enum), которое предоставляет удобные константы для работы с временем. Этот класс обычно используется вместе с классом ExecutorService из пакета java.util.concurrent для управления временем ожидания выполнения задач.

TimeUnit содержит константы для различных временных единиц, таких как наносекунды, микросекунды, миллисекунды, секунды, минуты и часы. Он предоставляет методы для конвертации времени из одной единицы в другую.

#для_продвинутых
👍18
#Вопросы_с_собеседования
Объясните процесс загрузки, инициализации, выполнения и выгрузки класса в Java Virtual Machine (JVM). Какие шаги выполняются на каждом этапе?


Ответ:

Загрузка (Loading):
— Нахождение и загрузка класс-файла: Class Loader ищет и загружает байт-код класса из файловой системы, JAR-архива, сети или другого источника.
— Создание структур данных: Создаются структуры данных для представления класса в памяти JVM, такие как Class объект.

Подготовка (Preparation):
— Выделение памяти для статических переменных: Выделяется память для статических переменных, инициализированных значением по умолчанию.

Инициализация (Initialization):
— Инициализация статических переменных и выполнение статических блоков: Статические переменные получают значения из кода инициализации, выполняются статические блоки.

Выполнение (Execution):
— Вызов метода main(): Если класс содержит метод public static void main(String[] args), JVM вызывает этот метод для выполнения программы.
— Вызов других методов: JVM вызывает другие методы по мере необходимости.

Выгрузка (Unloading):
— Освобождение памяти: Если класс больше не используется и нет активных ссылок на его объекты, JVM может выгрузить класс и освободить память.
👍21
RejectedExecutionHandler

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

#для_продвинутых
👍10
RecursiveTask<V>

RecursiveTask<V> является частью фреймворка Fork/Join в Java, введенного в Java 7. Этот фреймворк предоставляет удобный способ распараллеливания выполнения задач.

RecursiveTask<V> является подклассом ForkJoinTask<V>. Он предназначен для использования вместе с пулом Fork/Join (ForkJoinPool) и предоставляет специальные методы для разделения задачи на подзадачи и объединения результатов.

#для_продвинутых
👍9
ForkJoinPool.ManagedBlocker

ForkJoinPool.ManagedBlocker является интерфейсом в Java, который предоставляет механизм для блокировки потока внутри фреймворка ForkJoinPool. ForkJoinPool — это фреймворк параллельного выполнения введенный в Java 7.

Интерфейс ManagedBlocker предоставляет метод boolean block() и используется для реализации пользовательских операций, которые могут вызвать блокировку потока. Этот интерфейс обычно используется в ситуациях, когда задача внутри ForkJoinPool ожидает результат выполнения другой задачи, но не хочет приводить к блокировке потока.

#для_продвинутых
👍9
#Вопросы_с_собеседования
Если бы вы могли сравнить принципы работы Garbage Collector в Java с процессами в живой природе, какой был бы самый подходящий аналог и почему?

Garbage Collector в Java можно сравнить с процессом опадания и разложения листьев в лесу. Так же, как опавшие листья удаляются из экосистемы леса, освобождая место и питательные вещества для новых растений, Garbage Collector удаляет неиспользуемые объекты из памяти, освобождая ресурсы для новых объектов.
😁36👍122
Garbage Collection и JVM

JVM работает как хорошо отлаженный механизм, автоматически распределяя и освобождая память. Это и есть суть Garbage Collection. Это процесс, который автоматически находит и удаляет объекты, которые больше не используются вашим приложением. Благодаря этому, разработчики могут сосредоточиться на логике приложения, не беспокоясь о ручном управлении памятью.

Смотреть статью
👍162
#Вопросы_с_собеседования
Объясните принципы работы и использование Future и Callable в Java для выполнения асинхронных задач. Приведите пример кода с использованием Future и Callable.


Ответ:

Callable: Представляет собой задачу, которую можно выполнить и получить результат.
Future: Интерфейс, предназначенный для представления результата асинхронной операции. Он позволяет проверять статус завершения задачи, ожидать завершения и получать результат.

Объяснение:

ExecutorService executorService = Executors.newSingleThreadExecutor();: Создание ExecutorService с одним потоком.
Callable<String> callableTask = ...;: Создание объекта Callable, представляющего асинхронную задачу.
Future<String> future = executorService.submit(callableTask);: Подача задачи на выполнение и получение объекта Future, с помощью которого можно управлять и получать результат асинхронной задачи.
String result = future.get();: Ожидание завершения задачи и получение результата. Если задача еще не завершена, метод get() будет блокировать текущий поток до завершения задачи.
executorService.shutdown();: Завершение работы ExecutorService после завершения всех задач.

Примечание:
Использование Callable и Future полезно в ситуациях, когда вы хотите выполнить асинхронную задачу и получить результат её выполнения. Это может быть полезно в приложениях, где необходимо избегать блокировки главного потока ожиданием завершения долгих операций.
👍111
#Вопросы_с_собеседования
Реализуйте в Java собственную реализацию синглтона (singleton). Напишите код и объясните, как работает ваша реализация, а также какие проблемы могут возникнуть при использовании синглтона и как вы можете их решить.

Объяснение:

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

— Приватный конструктор: Конструктор класса сделан приватным, чтобы избежать создания экземпляров снаружи класса.
— Статический метод getInstance: Метод getInstance является статическим, чтобы можно было вызывать его без создания экземпляра класса. Внутри метода используется ленивая инициализация, то есть экземпляр создается только при первом вызове метода getInstance.
— Синхронизация: В рассмотренной реализации используется ключевое слово synchronized для обеспечения потокобезопасности при первом создании экземпляра. Однако это может сказаться на производительности. Существуют и другие подходы к обеспечению потокобезопасности, такие как использование volatile или двойной проверки.

Проблемы синглтона и их решения:

— Ленивая инициализация: В данной реализации используется ленивая инициализация, что может вызвать проблемы в многопоточной среде.
Решение: использование volatile или двойной проверки на null для обеспечения безопасной ленивой инициализации.
— Сериализация: При сериализации и десериализации синглтона могут возникнуть проблемы, поскольку каждая десериализация создаст новый объект.
Решение: переопределить методы readResolve и writeReplace для управления процессом сериализации и десериализации.
— Тестирование: Трудно провести тестирование, так как синглтон предоставляет глобальную точку доступа.
Решение: использование dependency injection (внедрение зависимостей) для более гибкого тестирования.
👍141🔥1
Инвалидация итераторов

Итераторы предоставляют удобный способ перебора элементов коллекций, таких как списки, множества и карты. Инвалидация итератора означает, что итератор больше не может быть использован для обхода коллекции из-за изменений, произведенных в коллекции после создания итератора.

Пример инвалидации итератора может возникнуть, если вы изменяете коллекцию (добавляете, удаляете элементы) во время итерации без использования методов, предоставляемых самим итератором или коллекцией для безопасного изменения.

Чтобы избежать инвалидации итератора, вы можете использовать методы, предоставленные самой коллекцией, такие как Iterator.remove() или использовать итераторы из пакета java.util.concurrent, которые могут обрабатывать изменения коллекции в процессе итерации.

#для_продвинутых
👍12
ListIterator

ListIterator — это интерфейс в Java, который предоставляет возможность итерации по элементам списка в обоих направлениях (вперед и назад). Этот интерфейс является частью Java Collections Framework и расширяет интерфейс Iterator.

#для_продвинутых
👍20
Немного о гигиене Java кода

Во время код-ревью или работы над новым проектом может раздражать многое: стиль, подходы, качество. Но больше всего расстраивает банальный недостаток гигиены кода. В связи с регулярностью проблемы хочется на неё обратить внимание и напомнить, как гигиену поддерживать.

Смотреть статью
👍92
#Вопросы_с_собеседования
В чем разница между ошибкой 'StackOverflowError' и 'OutOfMemoryError' в Java и какие стратегии можно использовать для их предотвращения?

'StackOverflowError' возникает, когда стек вызовов программы превышает свой лимит, обычно из-за глубокой или бесконечной рекурсии. Для предотвращения этого, следует ограничивать глубину рекурсии и использовать итеративные алгоритмы, где это возможно.

'OutOfMemoryError', с другой стороны, возникает, когда JVM исчерпывает доступную ей память, часто из-за чрезмерного создания объектов или утечек памяти. Чтобы предотвратить это, следует оптимизировать использование памяти в приложении, правильно управлять жизненным циклом объектов, и рассмотреть возможность увеличения объема памяти, выделяемой для JVM.
👍162
NavigableMap

NavigableMap является интерфейсом, который расширяет SortedMap и предоставляет дополнительные методы для навигации по отсортированной коллекции.

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

В этом примере мы используем различные методы навигации, такие как lowerEntry, floorEntry, ceilingEntry и higherEntry, чтобы найти ближайшие ключи к заданному значению. В конце мы создаем подмножество элементов с помощью метода subMap, указывая диапазон ключей.
👍15
Метод compareAndSwap()

Метод compareAndSwap() является одним из основных методов атомарных переменных в Java. Он используется для атомарного сравнения значения переменной с ожидаемым значением и, в случае успеха, записи нового значения в переменную.

Метод compareAndSwap() имеет четыре параметра:

объект — объект, в котором находится переменная.
переменная — переменная, значение которой необходимо сравнить и изменить.
ожидаемое значение — ожидаемое значение переменной.
новое значение — новое значение, которое необходимо записать в переменную.

Если значение переменной совпадает с ожидаемым значением, то метод compareAndSwap() изменяет значение переменной на новое. В противном случае метод compareAndSwap() возвращает значение переменной.

Код выше увеличивает значение переменной counter на 1. Если значение переменной counter в момент вызова compareAndSwap() равно 0, то метод успешно изменяет значение переменной на 1 и возвращает значение true. В противном случае метод возвращает false.

#для_продвинутых
👍121
Генерирация случайных чисел

Мы создадали метод, который будет использовать потоки (Streams) и лямбда-выражения для быстрого создания и обработки списка уникальных случайных чисел. Это демонстрирует мощь функционального программирования в Java.

В этом примере мы используем Random().ints() для генерации бесконечного потока случайных чисел в заданном диапазоне, затем применяем distinct() для фильтрации, чтобы оставить только уникальные значения. После этого ограничиваем количество чисел с помощью limit(size) и преобразуем их в список (List) с использованием collect(Collectors.toList()). Это эффективный способ генерации уникальных случайных чисел с использованием современных возможностей Java.
👍35
Метод weakCompareAndSwap()

Метод weakCompareAndSwap() является одним из методов класса AtomicReference, который предоставляет атомарные операции с переменными ссылочного типа. Метод weakCompareAndSwap() выполняет операцию сравнения и обмена (compare-and-swap), которая заключается в следующем:

1. Метод проверяет текущее значение переменной.
2. Если текущее значение переменной соответствует ожидаемому значению, то метод выполняет обмен этого значения на новое значение.
3. Если текущее значение переменной не соответствует ожидаемому значению, то метод ничего не делает.

Метод weakCompareAndSwap() отличается от метода compareAndSwap() тем, что он не гарантирует полную атомарность операции сравнения и обмена. Если текущее значение переменной не соответствует ожидаемому значению, то поведение метода не определено. Он может завершиться с ошибкой или вернуть false.

#для_продвинутых
👍12
Метааннотации

Метааннотации — это особые аннотации, которые используются для описания других аннотаций. Они позволяют определять параметры, которые будут применяться к аннотациям, а также правила, которые эти аннотации должны соблюдать.

Метааннотации могут использоваться для следующих целей:

— Определение параметров аннотаций. Метааннотации могут использоваться для определения параметров, которые будут применяться к аннотациям. Например, метааннотация @Retention определяет, когда аннотация будет доступна: в исходном коде, во время компиляции или во время выполнения.

— Определение правил для аннотаций. Метааннотации могут использоваться для определения правил, которые должны соблюдать аннотации. Метааннотация @Target определяет, к каким элементам кода можно применить аннотацию.

— Создание новых аннотаций. Метааннотации можно использовать для создания новых аннотаций. Например, можно использовать метааннотацию @Target для создания аннотации, которая может применяться только к классам.

#для_начинающих
👍152
Трюк с битовыми операциями

Этот код демонстрирует обмен значений двух переменных (a и b) без использования дополнительной временной переменной.

Он использует битовую операцию XOR (^). Ключевой момент здесь в том, что XOR двух одинаковых чисел возвращает 0, а XOR числа с 0 возвращает само это число. Таким образом, когда мы применяем XOR к a и b и затем обратно, мы фактически обмениваем их значения.
👍27😱1