Java Ready | Программирование
9.1K subscribers
1.42K photos
77 videos
1 file
747 links
Авторский канал по разработке на Java.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Cотрудничество: @energy_c
Download Telegram
Хорошая статья про обработку ошибок в Kafka!

Автор разбирает ситуацию, когда консьюмер не может обработать сообщение и снова упирается в тот же offset. Дальше показывает, как использовать Dead Letter Queue, retryable и non-retryable ошибки.

В статье автор показывает:
• почему ошибка десериализации может остановить консьюмера
• как настроить DeadLetterPublishingRecoverer в Spring Kafka
• зачем выносить проблемные сообщения в отдельный DLT процессор

Продолжай читать на Habr


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🔥2🤝2
Шпаргалка по контейнеризации Java-приложений!

Например, multi-stage build помогает не тащить инструменты сборки в production-образ, а .dockerignore убирает лишние файлы из build context.

На картинке собраны практики для Docker-образов с Java. Есть фиксированные base image теги, минимальный runtime, запуск не от root, обработка сигналов, graceful shutdown, .dockerignore и проверка уязвимостей.

Сохрани, чтобы не потерять!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥3🤝1
Собираем поиск по словам на Java!

Нужно быстро находить документы, где встречается слово. Сделаем небольшой inverted index, который хранит для каждого слова набор id документов.

Начнём с хранилища индекса:
Map<String, Set<Integer>> index = new HashMap<>();


Документ можно представить обычной строкой:
int id = 7;
String text = "Java streams and maps";


Разобьём текст на слова в нижнем регистре:
String[] words = text
.toLowerCase()
.split("\\W+");


Теперь добавим каждое слово в индекс:
for (String word : words) {
index.computeIfAbsent(word, k -> new HashSet<>())
.add(id);
}


Поиск становится простым обращением к map:
Set<Integer> result = index.getOrDefault(
"java",
Set.of()
);


Такой индекс не заменяет полноценный search engine, но хорошо показывает идею. Мы заранее строим структуру, чтобы потом быстро получать список документов по слову.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2🔥2🤝1
Шпаргалка по контейнеризации Java-приложений!

Например, multi-stage build помогает не тащить инструменты сборки в production-образ, а .dockerignore убирает лишние файлы из build context.

На картинке собраны практики для Docker-образов с Java. Есть фиксированные base image теги, минимальный runtime, запуск не от root, обработка сигналов, graceful shutdown, .dockerignore и проверка уязвимостей.

Сохрани, чтобы не потерять!

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2🔥2
Почему BigDecimal.equals может странно работать даже при одинаковом числе?

BigDecimal часто используют для денег, процентов и точных расчётов. Но сравнивать такие значения через equals не всегда то, что ожидается.

Посмотри на пример:
var a = new BigDecimal("1.0");
var b = new BigDecimal("1.00");

System.out.println(a.equals(b));


Математически это одно и то же значение. Но equals вернёт false, потому что BigDecimal сравнивает не только число, но и scale.

У этих объектов разный scale:
System.out.println(a.scale()); // 1
System.out.println(b.scale()); // 2


Для денежных расчётов это может быть неожиданно. Например, значение из базы пришло как 1.00, а значение из расчёта получилось как 1.0.

Если нужно сравнить именно числовое значение, используй compareTo:
if (a.compareTo(b) == 0) {
System.out.println("same value");
}


compareTo смотрит на математическое значение и не считает scale причиной различия.

А вот в коллекциях equals всё равно важен:
Set<BigDecimal> values = new HashSet<>();
values.add(new BigDecimal("1.0"));
values.add(new BigDecimal("1.00"));


В таком Set будет два элемента, потому что HashSet опирается на equals и hashCode.

Если тебе нужен единый формат, значение можно нормализовать:
var normalized = amount.stripTrailingZeros();


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

Для числового сравнения BigDecimal используй compareTo, а equals оставляй для случаев, где важен ещё и scale.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤5🔥5
Проверяем пересечение временных интервалов на Java!

Нужно понять, конфликтует ли новый слот с уже существующими. Такая задача встречается в календарях, бронированиях, расписаниях задач и системах записи.

В этой задаче:
• описываем интервал отдельным record
• пишем короткое правило пересечения
• фильтруем занятые слоты через stream
• получаем список конфликтов


Вместо набора частных случаев появляется одно универсальное условие.

👉 Java Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3🔥3
Знали, почему Pattern.compile лучше не вызывать в горячем цикле?

В Java регулярные выражения часто используют для валидации, поиска и очистки строк. Рабочий код выглядит так:
for (String email : emails) {
if (Pattern.compile(".+@.+\\..+").matcher(email).matches()) {
valid.add(email);
}
}


Проблема в том, что Pattern.compile создаёт объект шаблона. Если делать это на каждой итерации, программа снова и снова разбирает одно и то же выражение.

Для короткого списка разницы почти не видно. Но в обработке логов, CSV, API-ответов или очередей это превращается в лишнюю нагрузку.

Лучше скомпилировать шаблон один раз:
private static final Pattern EMAIL =
Pattern.compile(".+@.+\\..+");


А внутри цикла только создавать matcher:
for (String email : emails) {
if (EMAIL.matcher(email).matches()) {
valid.add(email);
}
}


Так код показывает, что регулярка постоянная, а не строится заново для каждой строки.

Если шаблон зависит от входных данных, его всё равно можно кешировать по ключу:
Pattern pattern = cache.computeIfAbsent(mask, Pattern::compile);


Но кешировать стоит только ограниченный набор шаблонов, чтобы не получить бесконечно растущую Map.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥4🤝1
Java 25 становится проще!

Автор разбирает JEP-512 и изменения, которые позволяют писать небольшие программы с меньшим количеством обязательной обвязки. Вместо класса, static main и ручных импортов можно сосредоточиться на самой задаче, а не на стартовом шаблоне.

В статье разбирают:
• как устроены упрощённые исходники Java 25
• зачем появились неявные импорты и класс IO
• как запускать короткие Java-скрипты из командной строки

Продолжай читать на Habr


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤4🔥3
Почему Files.lines() нельзя оставлять без try-with-resources?

Files.lines() выглядит как удобный способ быстро получить Stream строк из файла. Но за этим Stream остаётся открытый файловый ресурс.
Stream<String> lines = Files.lines(path);
long count = lines.count();


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

Правильнее ограничить жизнь Stream блоком try-with-resources.
try (Stream<String> lines = Files.lines(path)) {
long count = lines.count();
}


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

Если нужен небольшой файл целиком, можно взять готовый список строк.
List<String> lines = Files.readAllLines(path);


readAllLines проще, но читает файл полностью. Files.lines подходит для потоковой обработки, если не забывать закрывать ресурс.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥3
Напоминалка по устройству Java records!

На картинке показано, из каких частей состоит record и что генерирует компилятор.

Например, запись public record Person(String name, int age) создаёт final-поля, канонический конструктор, методы name(), age(), equals() и hashCode() без ручного шаблонного кода.

Сохрани, чтобы не потерять!

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥4