Java библиотека
31.6K subscribers
2.31K photos
85 videos
9 files
2.11K links
Книги, статьи, мемы и многое другое для Java программиста!

По сотрудничеству и рекламе: @NadikaKir

Канал в перечне РКН: https://vk.cc/cJrT4A

Мы на бирже: https://telega.in/c/javalib/

Сообщество VK https://vk.com/javatutorial
Download Telegram
🚀 Индексы в PostgreSQL

Когда сервис начинает работать с десятками миллионов строк, простое findById уже не выглядит «мгновенным». Тут в игру вступают индексы.

🔍 Что такое индекс

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

⚡️ Типы индексов и когда применять

— B-Tree (по умолчанию)

Отлично работает для операций =, <, >, ORDER BY.
Частый кейс: поиск по id, created_at, username.
CREATE INDEX idx_user_email ON users(email);


— GIN (Generalized Inverted Index)

Для jsonb, массивов и полнотекстового поиска.
Например, поиск по тегам или WHERE metadata @> '{"os":"android"}'.
CREATE INDEX idx_logs_metadata ON logs USING gin (metadata jsonb_path_ops);


— GiST (Generalized Search Tree)

Для геоданных, поиска по диапазонам (tsrange, daterange).
CREATE INDEX idx_places_geom ON places USING gist (geom);


— Hash Index

Для очень быстрого поиска по точному совпадению, но реже нужен (B-Tree почти всегда быстрее).
CREATE INDEX idx_sessions_sid ON sessions USING hash (session_id);


⚠️ На что обратить внимание

— Индекс ускоряет SELECT, но замедляет INSERT/UPDATE/DELETE (нужно обновлять и таблицу, и индекс).
— Слишком много индексов = «смерть от оптимизации». Держите баланс.
— Никогда не делайте индексы «на всё подряд». Индекс должен соответствовать реальным запросам.

А вы чаще оптимизируете запросы через индексы или через переписывание логики?

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍8🔥5🍾2
Media is too big
VIEW IN TELEGRAM
В Java нет двумерных массивов?

Есть ли разница между двумерным массивом и массивом массивов?

🌐🗣СМОТРЕТЬ VKVIDEO

📺🗣СМОТРЕТЬ RUTUBE

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍144🔥4
👩‍💻 Продвинутый совет по Spring Boot

Используй ApplicationPidFileWriter, чтобы при старте приложения записывать его PID в файл.
Это удобно для ops-скриптов, health-checks в контейнерах и мониторинга процессов. 🔥

🔜 Документация

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍157🔥7🎅1
⚙️ Async Profiler

Async Profiler — это современный профайлер для JVM, который показывает, где именно «горит» CPU и где происходят утечки памяти. В отличие от классических профайлеров, он использует низкоуровневые возможности ОС (perf, JVMTI) и практически не влияет на производительность.

📌 Что умеет:

— Делает CPU и allocation flame graph'ы
— Минимальный overhead
— Поддерживает анализ Java и нативного кода вместе
— Умеет снимать снапшоты и строить красивые SVG-отчёты

🧠 Особенно полезен, если у вас микросервисы или приложения с нагрузкой 24/7 — можно ловить узкие места без остановки сервиса.

🔗 Async Profiler на GitHub

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥4
Задачи с собеседований: Поиск первого уникального символа в строке (jun+)

— Как найти первый уникальный символ в строке?

🔘 Ключевые моменты:

- Используйте доп. структуру данных для хранения количества вхождений каждого символа
- Предложите в комментарии другие варианты решения.

Реализация через Map на картинке 👆

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥54
🖥 awesome-low-level-design — полезный репозиторий, который предназначен для изучения низкоуровневого проектирования (Low-Level Design, LLD) и подготовки к собеседованию на эту тему

🌟 Здесь содержатся ресурсы по основным принципам ООП, SOLID, паттернам проектирования, диаграммам UML и другим концепциям, а также задачи для практики проектирования различных систем. Решения задач написаны на разных ЯП, в том числе и на Java!

🔐 Лицензия: GPL-3.0

🖥 GitHub

@javalib #java
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍53
👩‍💻 Полезный приём в Java: record + sealed interface для удобных и безопасных доменных моделей.

С помощью sealed можно чётко ограничить набор допустимых типов, а record делает код компактным и иммутабельным.

Пример 👇

sealed interface Payment permits CardPayment, CashPayment, CryptoPayment {}

record CardPayment(String cardNumber, double amount) implements Payment {}
record CashPayment(double amount) implements Payment {}
record CryptoPayment(String wallet, double amount) implements Payment {}



Теперь можно использовать switch с исчерпывающей проверкой:


static String process(Payment p) {
return switch (p) {
case CardPayment c -> "Оплата картой: " + c.amount();
case CashPayment c -> "Оплата наличными: " + c.amount();
case CryptoPayment c -> "Крипта из кошелька: " + c.wallet();
};
}


Преимущества:

- меньше if/instanceof;
- компилятор гарантирует, что рассмотрены все варианты;
- код становится выразительным и легко расширяемым.

🔥 Такой подход отлично подходит для бизнес-логики: платежи, статусы заказов, события системы.

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1613🔥42
⚡️ JUnit 5: @ClassTemplate

В JUnit 5 появилась интересная аннотация @ClassTemplate. Она полезна, когда один и тот же набор тестов нужно выполнить в разных контекстах. Например: проверить класс с разными локалями, флагами или окружениями.

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

🔍 Как это работает

— Помечаем тестовый класс @ClassTemplate.
— Регистрируем ClassTemplateInvocationContextProvider, который возвращает список «контекстов» (например, en/it).
— JUnit прогоняет один и тот же класс для каждого контекста.

💡 Пример

— Есть Greeter, который должен возвращать приветствие по-английски и по-русски.
— Мы пишем один тест → JUnit запускает его дважды: для en и для ru.
— В отчёте два результата, код теста при этом один.

⚠️ Важные детали

— Работает начиная с JUnit 5.13.
— Для читаемых логов удобнее запускать через JUnit Console Launcher.
— Отличается от @TestTemplate тем, что переиспользует весь класс, а не отдельные методы.

А вы чаще решаете такие задачи параметризацией или дублированием тестов?

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍178🔥3
В чём разница между Statement и PreparedStatement?

— Statement используется для выполнения простых SQL-запросов без параметров. Он формирует запрос как строку и каждый раз компилирует его заново, что может быть медленно и небезопасно.

— PreparedStatement предварительно компилируется базой данных и позволяет задавать параметры через плейсхолдеры. Что повышает производительность при многократном выполнении одного запроса и защищает от SQL-инъекций (данные не конкатенируются со строкой запроса, а подставляются корректно).

Поэтому в реальных проектах почти всегда используют PreparedStatement.

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥14👍65🎄1
👩‍💻 Унификация API-ошибок в Spring Boot

Чёткая схема API помогает наладить диалог между провайдером и клиентом, а единый формат ошибок — избавить потребителей от хаоса в коде и лишних поводов для «боли».

🟢В Spring Boot по умолчанию структура ошибок выглядит так:

{
"timestamp": "2021-15-08T14:32:17.947+0000",
"status": 500,
"error": "Internal Server Error",
"path": "/test"
}


Такая форма ответа не всегда содержит тип ошибки для обработки на клиенте, а также предоставляет мало контекста для формирования пользовательских сообщений.

🟢Решение: разработать унифицированную структуру, например:

{
"error": {
"type": "USER_NOT_FOUND",
"message": "User with ID 12345 not found.",
"status": 500,
"path": "/integration/apps",
"timestamp": "2021-15-08T14:32:17.947+0000",
"data": {
"userId": "12345"
}
}
}


🟢Как внедрить:

🔘Создаём единое исключение AppException:
public final class AppException extends RuntimeException {
private final ErrorType type;
private Map<String, Object> data;
// конструктор и геттеры...
}
public enum ErrorType {
USER_NOT_FOUND(404), AUTHENTICATION_FAILED(401), …;
private final int status;
// геттеры...
}


🔘Глобальный обработчик:
Используем @ControllerAdvice с @ExceptionHandler(AppException.class) для перехвата ошибок и возвращения QErrorResponse, содержащего нужную структуру

🔘Обработка всех остальных ошибок:
Создаём свой ErrorController, заменяющий BasicErrorController, и возвращаем данные в таком же формате QErrorResponse:

@RestController
@RequestMapping("${server.error.path:${error.path:/error}}")
public class RestErrorController extends AbstractErrorController {
// логика формирования QErrorResponse…
}


Это гарантирует, что любые ошибки возвращаются в одинаковом формате .

🟢Почему это важно:

— Унификация ответа облегчает обработку ошибок на клиенте.
— Контекст в data позволяет выдавать более понятные сообщения пользователю.
— Расширяемость дает возможность добавлять новые типы ошибок при сохранении консистентности.

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
13🔥13👍8
Media is too big
VIEW IN TELEGRAM
TCP Log-appender на java (NIO)

В предыдущем видео TCP Log-сервер на java (NIO) был разработан TCP Log-сервер.
Сейчас для него сделаем appender для отправки логов.


🌐🗣СМОТРЕТЬ VKVIDEO

📺🗣СМОТРЕТЬ RUTUBE

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥3👍2
Задача с собеса: Потокобезопасный LRU-кэш с TTL (middle)

Интересная задачка с реального собеседования:

Компания хочет снизить нагрузку на БД и внешние API. Реализуйте in-memory кэш, который:

— хранит не более N элементов (LRU-политика вытеснения)
— истекает срок действия записей по TTL
— потокобезопасен и работает за O(1) на get/put


🔘Условия

1. put(k, v) кладёт значение с TTL (единый для экземпляра).
2. get(k) возвращает значение или null, если пары нет или истёк TTL.
3. При переполнении удаляется «наименее недавно использованный» элемент.
4. Решение должно быть неблокирующим по чтению или, как минимум, с короткими критическими секциями.
5. Допустимо ленивое удаление устаревших записей (на чтении/записи).

💡 Ключевые моменты:

— Выбор структуры: LinkedHashMap с accessOrder=true даёт LRU «из коробки».
— TTL: храните expireAt на элемент; чистите лениво и/или периодически.
— Потоки: короткие секции под ReentrantReadWriteLock (или один ReentrantLock) вокруг критичных операций.
— Амортизация O(1): не делайте полных проходов по карте на каждом вызове.

Возможная реализация в комментариях. Пишите также ваши реализация и способы оптимизации.

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥54😁1
👩‍💻 Основные улучшения Spring Boot 4

В новой версии Spring Boot 4, которая выйдет в ноябре 2025 года, разработчики получат ряд значительных улучшений, включая поддержку Jakarta EE 11, интеграцию с GraalVM 24 и улучшенную совместимость с Kotlin 2.2.

🟢Поддержка Jakarta EE 11
Spring Boot 4 перейдёт на Jakarta EE 11, что обеспечит поддержку Servlet 6.1, JPA 3.2 с Hibernate ORM 7.0 и Bean Validation 3.1. Это улучшит работу с веб-API и базами данных, а также обеспечит лучшую поддержку Kotlin и Java records.

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

🟢Совместимость с Kotlin 2.2
Spring Boot 4 улучшит работу с Kotlin 2.2, включая поддержку новых возможностей языка и улучшенную интеграцию со сборкой Gradle, что упростит разработку на Kotlin.

🟢Облачные технологии и контейнеризация
Улучшенные Buildpacks и более эффективная сборка Docker-образов обеспечат лучшую поддержку облачных технологий и контейнеризации, что упростит развертывание приложений.

🟢Безопасность
Spring Boot 4 будет основан на Spring Security 7, обеспечивая улучшенную интеграцию с OAuth 2.2 и OIDC, а также улучшенные криптографические настройки по умолчанию для повышения безопасности приложений.

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍178🔥3
Фишка дебага в IntelliJ IDEA: Reset Frame

Если вам приходилось перезапускать весь дебаг из-за ошибки в анализе кода, есть лучший способ – Reset Frame. Он позволяет откатить выполнение метода и повторить его выполнение с начала, без полной перезагрузки приложения.

🟢 Как использовать

1. Запускаем дебаг и доходим до брейкпоинта.
2. Открываем окно Debug.
3. Во вкладке Frames (стек вызовов) выбираем нужный метод.
4. Нажимаем ПКМ → Reset Frame.
5. Код откатится на вход в метод, как будто вы только что в него зашли.

🟢 Когда это полезно

— Ошиблись при анализе и хотите пересмотреть состояние переменных
— Нужно повторно выполнить метод, не перезапуская весь процесс
— Дебажите рекурсию или сложные цепочки вызовов

⚠️ Важно

— Reset Frame не откатывает глобальные изменения (например, изменения в базе или внешних файлах).
— Он работает только в пределах одного метода – не выйдет вернуть выполнение назад на несколько вызовов.

▪️ Как использовать Reset Frame эффективнее

Можно комбинировать его с Evaluate Expression, чтобы перед повторным вызовом метода изменять переменные вручную.

Пользовались Reset Frame раньше или только узнали?

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26👍104😁1