Три похожих слова в Java —
🔒
Ключевое слово. Используется для ограничений:
*
*
*
📌 Особенно важно для immutability и thread-safety.
🧯
Блок в конструкции
💡 Используется для освобождения ресурсов: закрытия потоков, соединений и т.д.
⚰️
Метод из
⚠️ УСТАРЕЛ с Java 9, удалён в Java 18. Не используй.
🔪 Непредсказуем, плохо работает, тормозит GC. Вместо него —
🧠 Важно не путать:
*
*
*
👉@BookJava
final
, finally
, finalize
— но смысл у них совершенно разный. Разберёмся 🧠🔒
final
Ключевое слово. Используется для ограничений:
*
final class
— нельзя наследовать.*
final method
— нельзя переопределить.*
final variable
— нельзя изменить значение (один раз присвоил — всё).📌 Особенно важно для immutability и thread-safety.
final int x = 10;
x = 20; // ошибка компиляции
🧯
finally
Блок в конструкции
try-catch-finally
. Выполняется всегда, даже если был return
или exception
.💡 Используется для освобождения ресурсов: закрытия потоков, соединений и т.д.
try {
// что-то может выбросить исключение
} catch (Exception e) {
// обработка ошибки
} finally {
// всегда выполнится
}
⚰️
finalize()
Метод из
Object
, вызывался перед удалением объекта сборщиком мусора.⚠️ УСТАРЕЛ с Java 9, удалён в Java 18. Не используй.
🔪 Непредсказуем, плохо работает, тормозит GC. Вместо него —
AutoCloseable
и try-with-resources
.
@Override
protected void finalize() throws Throwable {
System.out.println("До свидания...");
}
🧠 Важно не путать:
*
final
— про нельзя менять*
finally
— про всегда выполнится*
finalize
— про устаревший и бесполезный метод👉@BookJava
👍5
Ищете эффективные инструменты для создания DSL?
Узнайте, как Kotlin может упростить разработку с помощью JsonBuilder!
Приглашаем на открытый урок.
🗓 22 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».
На открытом уроке вы разберете, как Kotlin позволяет создавать DSL (Domain-Specific Languages), оптимизируя процесс разработки. Мы покажем теорию и практику создания DSL на примере JsonBuilder.
Вы не только научитесь создавать собственные DSL, но и освоите замыкания и extension-методы Kotlin, которые дадут вам дополнительные преимущества при написании чистого и гибкого кода.
🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Kotlin5
👉 Регистрация на вебинар: https://vk.cc/cMaDZP
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Узнайте, как Kotlin может упростить разработку с помощью JsonBuilder!
Приглашаем на открытый урок.
🗓 22 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».
На открытом уроке вы разберете, как Kotlin позволяет создавать DSL (Domain-Specific Languages), оптимизируя процесс разработки. Мы покажем теорию и практику создания DSL на примере JsonBuilder.
Вы не только научитесь создавать собственные DSL, но и освоите замыкания и extension-методы Kotlin, которые дадут вам дополнительные преимущества при написании чистого и гибкого кода.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Dependency Inversion Principle (D в SOLID)
Зависимости должны идти от высокоуровневой политики к низкоуровневым деталям, а не наоборот. Абстракции — хозяева, реализации — обслуживающий персонал.
📌 Коротко о сути
* Модули верхнего уровня (бизнес-логика) зависят только от интерфейсов/абстракций.
* Модули нижнего уровня (база, сеть, файлы) также зависят от тех же абстракций.
* Сами абстракции не знают ничего о деталях, тем самым разрывая «бетонную» сцепку между слоями.
💡 Мини-пример (Java 17+, Spring Boot 3+)
BillingService может жить в модульном jar без spring-email-starter и SMTP-кода — протестировать его теперь элементарно.
⚠️ Где рождаются проблемы
1. Путаница DI container ≠ DIP
IoC/DI-фреймворк (Spring, CDI) — лишь удобный способ «сращивать» зависимости, но принцип работает и без контейнера (чистый constructor injection).
2. Абстракции ради галочки
Интерфейс OneImplService с единственной реализацией ломает читаемость, тесты и автоконфиг 📉.
➜ Создавай абстракцию, когда реально нужны сменяемость, тестируемость или расширяемость.
3. Утечки деталей
Если интерфейс таскает DTO из слоя хранения, ты всё ещё «протёк» к базе. Держи контракты чистыми.
4. Слепая вера в фреймворк
Жизненный цикл бинов, прокси, lazy-init — магия мешает понимать, кто кем владеет.
➜ Всегда можешь собрать объект вручную в юнит-тесте. Если сложно — запах нарушения DIP.
5. Слишком много уровней абстракций
«Контроллер → сервис → менеджер → порт → адаптер → репозиторий» превращает код в матрёшку. Дизайн важнее количества слоёв.
📝 Практические советы
* Используй constructor injection по умолчанию. Поле
* Группируй интерфейсы по use-case, а не по технологии (например,
* В тестах не мокай фреймворк — мокай контракт.
* Для одноразовых реализаций начни с
* Проверка себя: можно ли запустить модуль верхнего уровня без нижнего? Если да — DIP соблюдён.
💬 Итог
DIP — это не про «везде интерфейсы» и не про «подключи Spring». Это про правильное направление зависимостей, которое делает код гибким, тестируемым и не заложником технологий. А проблемы возникают, когда путают инструмент с принципом и забывают, что абстракция должна прятать детали, а не выпячивать их.
👉@BookJava
Зависимости должны идти от высокоуровневой политики к низкоуровневым деталям, а не наоборот. Абстракции — хозяева, реализации — обслуживающий персонал.
📌 Коротко о сути
* Модули верхнего уровня (бизнес-логика) зависят только от интерфейсов/абстракций.
* Модули нижнего уровня (база, сеть, файлы) также зависят от тех же абстракций.
* Сами абстракции не знают ничего о деталях, тем самым разрывая «бетонную» сцепку между слоями.
💡 Мини-пример (Java 17+, Spring Boot 3+)
// 1️⃣ Абстракция — контракт
public interface NotificationSender {
void send(Message msg);
}
// 2️⃣ Верхний уровень — бизнес-служба
@Service
public class BillingService {
private final NotificationSender sender;
public BillingService(NotificationSender sender) {
this.sender = sender; // зависим от контракта
}
public void bill(Client c) {
// ...
sender.send(new Message("Invoice #42"));
}
}
// 3️⃣ Низкий уровень — деталь
@Component
public class EmailSender implements NotificationSender {
public void send(Message msg) {
// SMTP-магия
}
}
BillingService может жить в модульном jar без spring-email-starter и SMTP-кода — протестировать его теперь элементарно.
⚠️ Где рождаются проблемы
1. Путаница DI container ≠ DIP
IoC/DI-фреймворк (Spring, CDI) — лишь удобный способ «сращивать» зависимости, но принцип работает и без контейнера (чистый constructor injection).
2. Абстракции ради галочки
Интерфейс OneImplService с единственной реализацией ломает читаемость, тесты и автоконфиг 📉.
➜ Создавай абстракцию, когда реально нужны сменяемость, тестируемость или расширяемость.
3. Утечки деталей
Если интерфейс таскает DTO из слоя хранения, ты всё ещё «протёк» к базе. Держи контракты чистыми.
4. Слепая вера в фреймворк
Жизненный цикл бинов, прокси, lazy-init — магия мешает понимать, кто кем владеет.
➜ Всегда можешь собрать объект вручную в юнит-тесте. Если сложно — запах нарушения DIP.
5. Слишком много уровней абстракций
«Контроллер → сервис → менеджер → порт → адаптер → репозиторий» превращает код в матрёшку. Дизайн важнее количества слоёв.
📝 Практические советы
* Используй constructor injection по умолчанию. Поле
final
= явная зависимость.* Группируй интерфейсы по use-case, а не по технологии (например,
TransferPort
, а не JdbcTransferRepository
).* В тестах не мокай фреймворк — мокай контракт.
* Для одноразовых реализаций начни с
class
. Если появится второй вариант — быстро вынесешь интерфейс (IDE поможет).* Проверка себя: можно ли запустить модуль верхнего уровня без нижнего? Если да — DIP соблюдён.
💬 Итог
DIP — это не про «везде интерфейсы» и не про «подключи Spring». Это про правильное направление зависимостей, которое делает код гибким, тестируемым и не заложником технологий. А проблемы возникают, когда путают инструмент с принципом и забывают, что абстракция должна прятать детали, а не выпячивать их.
👉@BookJava
👍10👎1
📌 Stream API: забудьте про peek()
Метод
⚠️ Почему не стоит полагаться на peek()?
*
* Поведение зависит от терминальной операции: например, при некоторых оптимизациях JDK (особенно в параллельных стримах) вызов
💡 Пример опасного кода:
🧠 Лучший подход: используйте
✅ Правильная замена:
Если нужно выполнить действие над каждым элементом, используйте явный и безопасный подход:
Или вообще вынесите логику за пределы стрима.
🧹 Держите код понятным и безопасным — забудьте про
👉@BookJava
Метод
peek()
в Java Stream API выглядит удобным для отладки, но его использование в реальном коде часто приводит к проблемам.⚠️ Почему не стоит полагаться на peek()?
*
peek()
— промежуточная операция, которая не гарантирует вызов функции для каждого элемента стрима.* Поведение зависит от терминальной операции: например, при некоторых оптимизациях JDK (особенно в параллельных стримах) вызов
peek()
может быть пропущен или работать непредсказуемо.💡 Пример опасного кода:
List<String> names = Stream.of("Java", "Spring", "Hibernate")
.peek(System.out::println) // 👈 анти-паттерн!
.collect(Collectors.toList());
🧠 Лучший подход: используйте
peek()
исключительно для дебага, но никогда — для изменения состояния или важных операций.✅ Правильная замена:
Если нужно выполнить действие над каждым элементом, используйте явный и безопасный подход:
List<String> names = Stream.of("Java", "Spring", "Hibernate")
.map(name -> {
log.info("Processing: {}", name); // или другая логика
return name;
})
.collect(Collectors.toList());
Или вообще вынесите логику за пределы стрима.
🧹 Держите код понятным и безопасным — забудьте про
peek()
.👉@BookJava
👍7
💻 Модели межсервисного взаимодействия
Изучите различные модели взаимодействия между микросервисами и выберите оптимальный подход для вашего проекта
Приглашаем на открытый урок.
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Software Architect».
На вебинаре вы узнаете:
✔️ Основные принципы и типы межсервисного взаимодействия.
✔️ Синхронные и асинхронные модели взаимодействия: плюсы и минусы.
✔️ Использование API Gateway и Service Mesh для управления трафиком.
✔️ Паттерны и лучшие практики для надежного и масштабируемого взаимодействия.
✔️ Примеры успешных реализаций межсервисного взаимодействия в реальных проектах.
Вебинар будет полезен:
- Разработчикам, работающим с микросервисной архитектурой.
- Архитекторам ПО, стремящимся оптимизировать межсервисное взаимодействие.
- Backend и Fullstack разработчикам, заинтересованным в улучшении взаимодействия между сервисами.
- DevOps-инженерам, отвечающим за развертывание и управление микросервисами.
🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - SoftwareArc_06
👉 Регистрация на вебинар: https://vk.cc/cMcrjZ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Изучите различные модели взаимодействия между микросервисами и выберите оптимальный подход для вашего проекта
Приглашаем на открытый урок.
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Software Architect».
На вебинаре вы узнаете:
Вебинар будет полезен:
- Разработчикам, работающим с микросервисной архитектурой.
- Архитекторам ПО, стремящимся оптимизировать межсервисное взаимодействие.
- Backend и Fullstack разработчикам, заинтересованным в улучшении взаимодействия между сервисами.
- DevOps-инженерам, отвечающим за развертывание и управление микросервисами.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
📌 Обход коллекций в Java: делаем правильно!
Часто вижу, как разработчики по привычке используют старый подход с циклом
🧠 1. Foreach (Java 5+)
Коротко, ясно, подходит для большинства задач:
🧠 2. Метод forEach (Java 8+)
Отлично подходит для функционального стиля:
⚠️ Важно: нельзя модифицировать саму коллекцию во время такого обхода!
🧠 3. Stream API (Java 8+)
Идеален для сложной обработки с фильтрацией, маппингом и т.д.:
💡 Что выбрать?
* Простой перебор? Используй цикл foreach.
* Нужно быстро и функционально?
* Сложные манипуляции? Только Stream API.
📌 Используйте современные подходы, это читаемость и удобство поддержки вашего кода!
👉@BookJava
Часто вижу, как разработчики по привычке используют старый подход с циклом
for
. Сегодня напомню оптимальные способы перебора коллекций в Java.🧠 1. Foreach (Java 5+)
Коротко, ясно, подходит для большинства задач:
for (String item : collection) {
// обработка элемента
}
🧠 2. Метод forEach (Java 8+)
Отлично подходит для функционального стиля:
collection.forEach(item -> {
// обработка элемента
});
⚠️ Важно: нельзя модифицировать саму коллекцию во время такого обхода!
🧠 3. Stream API (Java 8+)
Идеален для сложной обработки с фильтрацией, маппингом и т.д.:
collection.stream()
.filter(Objects::nonNull)
.map(String::toUpperCase)
.forEach(System.out::println);
💡 Что выбрать?
* Простой перебор? Используй цикл foreach.
* Нужно быстро и функционально?
collection.forEach()
.* Сложные манипуляции? Только Stream API.
📌 Используйте современные подходы, это читаемость и удобство поддержки вашего кода!
👉@BookJava
👍7
🔐 Основы сжатия данных: создаем RLE архиватор
Приглашаем на открытый урок.
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».
На этом вебинаре мы начнем создавать собственный архиватор на Java. Разработаем базовую структуру программы с пользовательским интерфейсом и реализуем алгоритм RLE (кодирование длин серий) для сжатия данных. Изучим как базовую, так и улучшенную версию RLE.
Протестируем эффективность алгоритма на разных типах файлов и увидим, когда этот простой метод сжатия работает наиболее эффективно.
Практическое погружение в мир алгоритмов сжатия данных для всех, кто интересуется программированием и структурами данных.
🎁 Всем участникам вебинара дарим промокод, который дает скидку на обучение - Algo5
👉 Регистрация на вебинар: https://vk.cc/cMenHb
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Приглашаем на открытый урок.
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».
На этом вебинаре мы начнем создавать собственный архиватор на Java. Разработаем базовую структуру программы с пользовательским интерфейсом и реализуем алгоритм RLE (кодирование длин серий) для сжатия данных. Изучим как базовую, так и улучшенную версию RLE.
Протестируем эффективность алгоритма на разных типах файлов и увидим, когда этот простой метод сжатия работает наиболее эффективно.
Практическое погружение в мир алгоритмов сжатия данных для всех, кто интересуется программированием и структурами данных.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Проверяешь аргументы вручную? Используй мощь системы типов Java!
📌 Ситуация: часто в методах видишь явные проверки вроде:
⚠️ Это шумно и ненадежно: легко пропустить проверку или некорректно сформулировать сообщение.
💡 Современный подход (Java 17+): явно обозначь контракт метода через типы и аннотации, и пусть JVM делает проверки автоматически!
Используй стандартные средства:
или лаконично через Lombok:
🔸 Преимущества:
* Ясность кода и контракта.
* Меньше boilerplate и человеческого фактора.
* Fail fast: сразу ловим ошибки, не откладывая.
🧠 Запомни: чем строже твоя система типов и контрактов, тем меньше неожиданностей в продакшене.
👉@BookJava
📌 Ситуация: часто в методах видишь явные проверки вроде:
public void process(User user) {
if (user == null || user.getName() == null) {
throw new IllegalArgumentException("User или его имя не могут быть null");
}
// код обработки...
}
⚠️ Это шумно и ненадежно: легко пропустить проверку или некорректно сформулировать сообщение.
💡 Современный подход (Java 17+): явно обозначь контракт метода через типы и аннотации, и пусть JVM делает проверки автоматически!
Используй стандартные средства:
import java.util.Objects;
public void process(User user) {
Objects.requireNonNull(user, "User не должен быть null");
Objects.requireNonNull(user.getName(), "Имя пользователя не должно быть null");
// код обработки...
}
или лаконично через Lombok:
import lombok.NonNull;
public void process(@NonNull User user) {
// Lombok автоматически вставит проверку на null
}
🔸 Преимущества:
* Ясность кода и контракта.
* Меньше boilerplate и человеческого фактора.
* Fail fast: сразу ловим ошибки, не откладывая.
🧠 Запомни: чем строже твоя система типов и контрактов, тем меньше неожиданностей в продакшене.
👉@BookJava
👍9👎3
👍3
🔥 Хардкорный тест для разработчиков, тимлидов и архитекторов!
💻 Ответьте на 11 вопросов и узнайте, достаточно ли у вас знаний, чтобы пройти онлайн-курс «Software Architect» в OTUS по спец.цене.
🦾 Курс поможет прокачать весь арсенал навыков, необходимых архитектору ПО.
❇️ Пройти тест - https://vk.cc/cMj0Ns
💣 Знание продвинутых техник построения архитектуры — это топ-компетенции для программистов в 2025 году. За 4 месяца обучения вы изучите тактики работы с атрибутами качества и архитектурные решения, а также узнаете, как проектировать архитектуру мобильных приложений, микросервисов, баз данных и ML архитектуру пайплайнов.
🎁 Для получения спец.цены используйте промокод, который дает скидку на обучение - SoftwareArc_06
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
💻 Ответьте на 11 вопросов и узнайте, достаточно ли у вас знаний, чтобы пройти онлайн-курс «Software Architect» в OTUS по спец.цене.
🦾 Курс поможет прокачать весь арсенал навыков, необходимых архитектору ПО.
❇️ Пройти тест - https://vk.cc/cMj0Ns
💣 Знание продвинутых техник построения архитектуры — это топ-компетенции для программистов в 2025 году. За 4 месяца обучения вы изучите тактики работы с атрибутами качества и архитектурные решения, а также узнаете, как проектировать архитектуру мобильных приложений, микросервисов, баз данных и ML архитектуру пайплайнов.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 10 правил безопасного Java-приложения:
1️⃣ Валидация на всех уровнях.
📌 Всегда проверяй входные данные (API, формы, запросы к БД). Используй Bean Validation (
2️⃣ Используй PreparedStatement.
⚠️ Никогда не конкатенируй SQL-запросы напрямую, чтобы избежать SQL-инъекций.
3️⃣ Не раскрывай детали исключений.
📌 Отправляй клиенту общий код ошибки, а детали логируй.
4️⃣ Скрывай конфигурацию.
💡 Используй
5️⃣ Ограничивай доступ.
📌 Spring Security — твой друг. Используй
6️⃣ Безопасная сериализация.
⚠️ Избегай Java-стандартной сериализации. Предпочитай JSON (Jackson) с явными DTO.
7️⃣ Используй актуальные версии библиотек.
📌 Регулярно проверяй зависимости (
8️⃣ Грамотно логируй.
💡 Не логируй пароли, токены и персональные данные. Используй SLF4J с Logback, настрой уровень логов.
9️⃣ Безопасные куки и заголовки.
📌 Используй атрибуты куки:
🔟 Настрой Security Headers.
📌 Используй заголовки:
*
*
*
Безопасность — это не разовая задача, а процесс 💡
👉@BookJava
1️⃣ Валидация на всех уровнях.
📌 Всегда проверяй входные данные (API, формы, запросы к БД). Используй Bean Validation (
@Valid
, @NotNull
).2️⃣ Используй PreparedStatement.
⚠️ Никогда не конкатенируй SQL-запросы напрямую, чтобы избежать SQL-инъекций.
3️⃣ Не раскрывай детали исключений.
📌 Отправляй клиенту общий код ошибки, а детали логируй.
4️⃣ Скрывай конфигурацию.
💡 Используй
application.yml
с переменными окружения для чувствительных данных (пароли, ключи API).5️⃣ Ограничивай доступ.
📌 Spring Security — твой друг. Используй
@PreAuthorize
и грамотно настраивай роли и права доступа.6️⃣ Безопасная сериализация.
⚠️ Избегай Java-стандартной сериализации. Предпочитай JSON (Jackson) с явными DTO.
7️⃣ Используй актуальные версии библиотек.
📌 Регулярно проверяй зависимости (
dependency-check
), чтобы избежать известных уязвимостей.8️⃣ Грамотно логируй.
💡 Не логируй пароли, токены и персональные данные. Используй SLF4J с Logback, настрой уровень логов.
9️⃣ Безопасные куки и заголовки.
📌 Используй атрибуты куки:
Secure
, HttpOnly
, SameSite
. Spring Security поможет тебе настроить это быстро.🔟 Настрой Security Headers.
📌 Используй заголовки:
*
X-Frame-Options: DENY
*
X-Content-Type-Options: nosniff
*
Content-Security-Policy
(CSP)Безопасность — это не разовая задача, а процесс 💡
👉@BookJava
👍11❤1
Двоичная Java: CDS, CRaC и AOT для ускорения запуска и прогрева JVM
В этой статье вы узнаете о повышении перфоманса Java-приложений. Разберём:
🔹Как работает HotSpot.
🔹Процессы исполнения байт-кода и в чём же основные проблемы.
🔹Технологии для повышения перформанса: CDS, CRaC и AOT.
🔹Два мира сборки приложений: статический и динамический.
Поговорим о двух болях, которые есть в Java-приложениях — это время запуска и время достижения пиковой производительности.
https://habr.com/ru/companies/axiomjdk/articles/911568/
👉@BookJava
В этой статье вы узнаете о повышении перфоманса Java-приложений. Разберём:
🔹Как работает HotSpot.
🔹Процессы исполнения байт-кода и в чём же основные проблемы.
🔹Технологии для повышения перформанса: CDS, CRaC и AOT.
🔹Два мира сборки приложений: статический и динамический.
Поговорим о двух болях, которые есть в Java-приложениях — это время запуска и время достижения пиковой производительности.
https://habr.com/ru/companies/axiomjdk/articles/911568/
👉@BookJava
👍2❤1
Хотите узнать, как работают алгоритмы сжатия данных?
В нашем вебинаре мы шаг за шагом создадим архиватор на Java, используя алгоритм RLE. Вы разработаете интерфейс программы и поймете, как реализовать самые эффективные методы сжатия.
Протестировав алгоритм на реальных данных, вы увидите, когда он работает наилучшим образом. Присоединяйтесь к нам и погрузитесь в мир программирования и алгоритмов!
🗓 28 мая в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Алгоритмы и структуры данных».
🎁
👉 Регистрация на вебинар: https://vk.cc/cMl0ID
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡1
Сегодня покажу вам интересный костыль, который до сих пор живёт в JDK и влияет на сортировку списков.
🧠 Если ты когда-нибудь пробовал сортировать LinkedList через
📌
⚠️ Но если это LinkedList (или любой не-рандом-доступ список), внутри происходит... преобразование списка в массив! Сначала все элементы копируются в массив, потом сортируются, а затем результат обратно заливается в твой список.
💡 Почему так? Сортировка напрямую через LinkedList была бы очень медленной — доступ к элементам по индексу у него O(n), а не O(1) как у ArrayList. Поэтому JDK идёт на компромисс: временная потеря памяти, но ускорение времени сортировки.
⚠️ Следствие: если у тебя большой LinkedList, сортировка будет требовать двойную память: сначала весь список копируется в массив.
Совет:
Для больших коллекций, которые часто сортируются, используй ArrayList, либо готовься к затратам памяти.
👉@BookJava
🧠 Если ты когда-нибудь пробовал сортировать LinkedList через
Collections.sort()
, знай — под капотом происходит скрытая магия.📌
Collections.sort(list)
сначала проверяет, какой это список. Если это RandomAccess-list (например, ArrayList) — используется быстрый сортировщик (TimSort) прямо по массиву.⚠️ Но если это LinkedList (или любой не-рандом-доступ список), внутри происходит... преобразование списка в массив! Сначала все элементы копируются в массив, потом сортируются, а затем результат обратно заливается в твой список.
// Да, это реально работает так:
List<Integer> list = new LinkedList<>();
// ...заполняем...
Collections.sort(list);
💡 Почему так? Сортировка напрямую через LinkedList была бы очень медленной — доступ к элементам по индексу у него O(n), а не O(1) как у ArrayList. Поэтому JDK идёт на компромисс: временная потеря памяти, но ускорение времени сортировки.
⚠️ Следствие: если у тебя большой LinkedList, сортировка будет требовать двойную память: сначала весь список копируется в массив.
Совет:
Для больших коллекций, которые часто сортируются, используй ArrayList, либо готовься к затратам памяти.
👉@BookJava
👍9🤓3
🧠 Как быстро написать компаратор в Java и не забыть про null
Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из
📌
📌
📌
💡 Такой подход краткий, читабельный и отлично работает с любыми полями, даже если они могут быть null.
⚠️ Никогда не забывай про null, особенно если сортируешь данные из БД или внешних источников. Ошибка
👉@BookJava
Часто нужно сортировать коллекции по какому-то полю. Вместо старых анонимных классов используем лямбды и статические методы из
Comparator
:
List<User> users = ...;
users.sort(Comparator
.comparing(User::getName, Comparator.nullsLast(String::compareToIgnoreCase))
.thenComparingInt(User::getAge)
);
📌
comparing
— сравнивает по полю (например, name).📌
nullsLast
или nullsFirst
— удобно обрабатывать возможные null.📌
thenComparingInt
— дополнительная сортировка (например, по возрасту).💡 Такой подход краткий, читабельный и отлично работает с любыми полями, даже если они могут быть null.
⚠️ Никогда не забывай про null, особенно если сортируешь данные из БД или внешних источников. Ошибка
NullPointerException
во время сортировки может неожиданно прилететь в проде.👉@BookJava
👍4
Ищем Java-разработчика в команду онлайн-рекомендаций AI VK 🤖
Будем вместе разрабатывать высоконагруженные микросервисы на Java. Кроме кода доверим коллеге принимать архитектурные и технические решения, гибко настраивать ML-эксперименты и рекомендательный пайплайн.
Если любите технически сложные задачи и хотите работать с большими данными, ждём ваше резюме на сайте VK Team!
Будем вместе разрабатывать высоконагруженные микросервисы на Java. Кроме кода доверим коллеге принимать архитектурные и технические решения, гибко настраивать ML-эксперименты и рекомендательный пайплайн.
Если любите технически сложные задачи и хотите работать с большими данными, ждём ваше резюме на сайте VK Team!
🤮2
🧠 Сегодня разберём Saga — паттерн, который часто всплывает на собеседованиях уровня сеньор, особенно если речь о микросервисах.
📌 Зачем нужна Saga?
Когда нужно выполнить бизнес-операцию, затрагивающую несколько микросервисов, важно обеспечить целостность данных. Классические транзакции (
💡 Виды Saga
1. Choreography
Нет единого оркестратора. Каждый сервис реагирует на события предыдущих через очередь (Kafka, RabbitMQ).
* Простой flow
* Меньше точек отказа
2. Orchestration
Есть выделенный "оркестратор", который координирует выполнение саги, рассылая команды сервисам.
* Более явный контроль
* Лучше трассировка
⚖️ Плюсы
* Обеспечивает согласованность между сервисами
* Высокая отказоустойчивость: каждый шаг можно компенсировать
* Гибкость — легко расширять и модифицировать бизнес-логику
⚠️ Минусы
* Сложнее реализовать, чем простые транзакции
* Не моментальная консистентность — возможны временные аномалии
* Нужно проектировать compensating transactions для каждого шага
* Тяжело тестировать крайние случаи и "сорванные" шаги
🔁 Альтернативы
* Distributed Transactions (XA, 2PC) — редко используются из-за сложности и слабой поддержки в современных cloud-системах.
* Event Sourcing — другой паттерн работы с изменениями, но сложнее для чтения.
* Idempotency + Retry — иногда достаточно, если бизнес-процесс допускает.
💡 Совет: для большинства бизнес-операций с межсервисным взаимодействием, где требуется отмена — Saga остаётся самым практичным выбором. В Spring есть библиотека Axon Framework, также стоит посмотреть на Camunda.
👉@BookJava
📌 Зачем нужна Saga?
Когда нужно выполнить бизнес-операцию, затрагивающую несколько микросервисов, важно обеспечить целостность данных. Классические транзакции (
@Transactional
) тут не подходят — нет распределённого ACID. Saga решает эту проблему через последовательность локальных транзакций с возможностью отката (compensation).💡 Виды Saga
1. Choreography
Нет единого оркестратора. Каждый сервис реагирует на события предыдущих через очередь (Kafka, RabbitMQ).
* Простой flow
* Меньше точек отказа
2. Orchestration
Есть выделенный "оркестратор", который координирует выполнение саги, рассылая команды сервисам.
* Более явный контроль
* Лучше трассировка
⚖️ Плюсы
* Обеспечивает согласованность между сервисами
* Высокая отказоустойчивость: каждый шаг можно компенсировать
* Гибкость — легко расширять и модифицировать бизнес-логику
⚠️ Минусы
* Сложнее реализовать, чем простые транзакции
* Не моментальная консистентность — возможны временные аномалии
* Нужно проектировать compensating transactions для каждого шага
* Тяжело тестировать крайние случаи и "сорванные" шаги
🔁 Альтернативы
* Distributed Transactions (XA, 2PC) — редко используются из-за сложности и слабой поддержки в современных cloud-системах.
* Event Sourcing — другой паттерн работы с изменениями, но сложнее для чтения.
* Idempotency + Retry — иногда достаточно, если бизнес-процесс допускает.
💡 Совет: для большинства бизнес-операций с межсервисным взаимодействием, где требуется отмена — Saga остаётся самым практичным выбором. В Spring есть библиотека Axon Framework, также стоит посмотреть на Camunda.
👉@BookJava
👍7❤1🔥1