Проверяем пересечение временных интервалов на Java!
Нужно понять, конфликтует ли новый слот с уже существующими. Такая задача встречается в календарях, бронированиях, расписаниях задач и системах записи.
В этой задаче:
Вместо набора частных случаев появляется одно универсальное условие.
👉 Java Ready | #задача
Нужно понять, конфликтует ли новый слот с уже существующими. Такая задача встречается в календарях, бронированиях, расписаниях задач и системах записи.
В этой задаче:
• описываем интервал отдельным record
• пишем короткое правило пересечения
• фильтруем занятые слоты через stream
• получаем список конфликтов
Вместо набора частных случаев появляется одно универсальное условие.
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 регулярные выражения часто используют для валидации, поиска и очистки строк. Рабочий код выглядит так:
Проблема в том, что Pattern.compile создаёт объект шаблона. Если делать это на каждой итерации, программа снова и снова разбирает одно и то же выражение.
Для короткого списка разницы почти не видно. Но в обработке логов, CSV, API-ответов или очередей это превращается в лишнюю нагрузку.
Лучше скомпилировать шаблон один раз:
А внутри цикла только создавать matcher:
Так код показывает, что регулярка постоянная, а не строится заново для каждой строки.
Если шаблон зависит от входных данных, его всё равно можно кешировать по ключу:
Но кешировать стоит только ограниченный набор шаблонов, чтобы не получить бесконечно растущую Map.
👉 Java Ready | #совет
В 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.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥4🤝1
Java 25 становится проще!
Автор разбирает JEP-512 и изменения, которые позволяют писать небольшие программы с меньшим количеством обязательной обвязки. Вместо класса, static main и ручных импортов можно сосредоточиться на самой задаче, а не на стартовом шаблоне.
В статье разбирают:
• как устроены упрощённые исходники Java 25
• зачем появились неявные импорты и класс IO
• как запускать короткие Java-скрипты из командной строки
👉 Java Ready | #статья
Автор разбирает JEP-512 и изменения, которые позволяют писать небольшие программы с меньшим количеством обязательной обвязки. Вместо класса, static main и ручных импортов можно сосредоточиться на самой задаче, а не на стартовом шаблоне.
В статье разбирают:
• как устроены упрощённые исходники Java 25
• зачем появились неявные импорты и класс IO
• как запускать короткие Java-скрипты из командной строки
Продолжай читать на Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍5🔥3
Почему Files.lines() нельзя оставлять без try-with-resources?
Files.lines() выглядит как удобный способ быстро получить Stream строк из файла. Но за этим Stream остаётся открытый файловый ресурс.
После count поток может быть исчерпан, но файл не обязан закрыться сразу. В долгоживущем сервисе или цикле обработки это приводит к накоплению открытых дескрипторов.
Правильнее ограничить жизнь Stream блоком try-with-resources.
Java закроет поток даже при исключении внутри обработки. Это особенно полезно для больших логов, CSV-файлов и пакетных задач, где не хочется загружать всё содержимое в память.
Если нужен небольшой файл целиком, можно взять готовый список строк.
readAllLines проще, но читает файл полностью. Files.lines подходит для потоковой обработки, если не забывать закрывать ресурс.
👉 Java Ready | #совет
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 подходит для потоковой обработки, если не забывать закрывать ресурс.
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 | #совет
На картинке показано, из каких частей состоит record и что генерирует компилятор.
Например, запись public record Person(String name, int age) создаёт final-поля, канонический конструктор, методы name(), age(), equals() и hashCode() без ручного шаблонного кода.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤5🔥5
Как получить оффер, лежа на пляже?
История Маши - frontend-разработчицы.
2 месяца она искала работу сама:
читала вакансии, сравнивала требования, откликалась вручную.
Потом подключила ИИ-ассистента Софи…
и уехала в отпуск.
Пока Маша отдыхала, Софи сделала 200 откликов.
Результат:
• 15 интервью
• 7 тестовых
• оффер
Самое неожиданное - зарплата почти в 2 раза выше, чем была указана в резюме.
Зайти на 3 бесплатных дня в Софи можно уже сейчас.
Регистрируйся здесь.
История Маши - frontend-разработчицы.
2 месяца она искала работу сама:
читала вакансии, сравнивала требования, откликалась вручную.
Потом подключила ИИ-ассистента Софи…
и уехала в отпуск.
Пока Маша отдыхала, Софи сделала 200 откликов.
Результат:
• 15 интервью
• 7 тестовых
• оффер
Самое неожиданное - зарплата почти в 2 раза выше, чем была указана в резюме.
Зайти на 3 бесплатных дня в Софи можно уже сейчас.
Регистрируйся здесь.
👎3❤1
Запускаем внешнюю команду через ProcessBuilder!
Иногда Java-приложению нужно вызвать системную утилиту, например git, ffmpeg или собственный скрипт деплоя. Склеивать такую команду в одну строку опасно, особенно если параметры приходят извне.
ProcessBuilder принимает аргументы отдельно. Так пробелы и специальные символы не превращаются в случайный shell-код.
redirectErrorStream(true) объединяет обычный вывод и ошибки. Это не даёт процессу зависнуть, когда буфер stderr заполняется, пока приложение читает только stdout.
После чтения обязательно дождитесь завершения и проверьте код возврата. Нулевой код обычно означает успех.
Для долгих команд добавьте waitFor с таймаутом и уничтожайте процесс при превышении лимита. Так интеграция с внешним инструментом не сможет навсегда заблокировать поток приложения.
👉 Java Ready | #практика
Иногда Java-приложению нужно вызвать системную утилиту, например git, ffmpeg или собственный скрипт деплоя. Склеивать такую команду в одну строку опасно, особенно если параметры приходят извне.
ProcessBuilder принимает аргументы отдельно. Так пробелы и специальные символы не превращаются в случайный shell-код.
var process = new ProcessBuilder(
"git", "status", "--short")
.redirectErrorStream(true)
.start();
redirectErrorStream(true) объединяет обычный вывод и ошибки. Это не даёт процессу зависнуть, когда буфер stderr заполняется, пока приложение читает только stdout.
try (var reader = process.inputReader()) {
var lines = reader.lines().toList();
lines.forEach(System.out::println);
}После чтения обязательно дождитесь завершения и проверьте код возврата. Нулевой код обычно означает успех.
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IllegalStateException("Command failed");
}
Для долгих команд добавьте waitFor с таймаутом и уничтожайте процесс при превышении лимита. Так интеграция с внешним инструментом не сможет навсегда заблокировать поток приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2🔥2