Почему Stream.toList() может сломать старый код?
В Java часто собирают stream в список:
Выглядит почти так же, как старый вариант через Collectors:
Но есть важное отличие.
Stream.toList() возвращает неизменяемый список:
Если список нужен только для чтения, это даже плюс:
Так код явно показывает, что результат не должен случайно меняться после сборки.
Но если дальше список нужно дополнять, лучше создать изменяемую коллекцию явно:
Или сделать копию:
👉 Java Ready | #совет
В Java часто собирают stream в список:
List<String> names = users.stream()
.map(User::name)
.toList();
Выглядит почти так же, как старый вариант через Collectors:
List<String> names = users.stream()
.map(User::name)
.collect(Collectors.toList());
Но есть важное отличие.
Stream.toList() возвращает неизменяемый список:
List<String> names = users.stream()
.map(User::name)
.toList();
names.add("admin"); // UnsupportedOperationException
Если список нужен только для чтения, это даже плюс:
return users.stream()
.filter(User::active)
.map(User::name)
.toList();
Так код явно показывает, что результат не должен случайно меняться после сборки.
Но если дальше список нужно дополнять, лучше создать изменяемую коллекцию явно:
List<String> names = users.stream()
.map(User::name)
.collect(Collectors.toCollection(ArrayList::new));
Или сделать копию:
List<String> names = new ArrayList<>(
users.stream().map(User::name).toList()
);
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍4🔥3
Шпаргалка по Spring-аннотациям в Java!
Например, @RestController объединяет контроллер и @ResponseBody, а @Autowired связывает зависимости внутри Spring-компонента.
На картинке основные Spring Boot, Web и Framework-аннотации: @SpringBootApplication, @Controller, @RequestMapping, @PathVariable, @Configuration, @ComponentScan, @Service, @Bean, @Primary, @Profile и другие.
Сохрани, чтобы не потерять!
👉 Java Ready | #ресурс
Например, @RestController объединяет контроллер и @ResponseBody, а @Autowired связывает зависимости внутри Spring-компонента.
На картинке основные Spring Boot, Web и Framework-аннотации: @SpringBootApplication, @Controller, @RequestMapping, @PathVariable, @Configuration, @ComponentScan, @Service, @Bean, @Primary, @Profile и другие.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥5👍4
Делаем простой retry для нестабильной операции в Java!
В реальных приложениях операции иногда падают временно: сеть моргнула, сервис ответил 503, база не успела принять соединение. В таких случаях полезно повторить действие несколько раз, а не сразу завершать сценарий ошибкой.
Опишем функциональный интерфейс для операции:
Теперь зададим количество попыток:
И задержку между ними:
Базовая идея такая:
Но нужно сохранить последнюю ошибку, если все попытки закончились неудачей:
Соберём retry в метод:
Теперь можно обернуть нестабильную операцию:
Если операция сработает со второй или третьей попытки, код продолжит выполнение. Если нет, наружу уйдёт последняя ошибка.
В production-коде к retry часто добавляют экспоненциальную задержку, логирование и ограничение по типам исключений.
👉 Java Ready | #практика
В реальных приложениях операции иногда падают временно: сеть моргнула, сервис ответил 503, база не успела принять соединение. В таких случаях полезно повторить действие несколько раз, а не сразу завершать сценарий ошибкой.
Опишем функциональный интерфейс для операции:
@FunctionalInterface
interface ThrowingSupplier<T> {
T get() throws Exception;
}
Теперь зададим количество попыток:
int attempts = 3;
И задержку между ними:
Duration delay = Duration.ofMillis(300);
Базовая идея такая:
try {
return action.get();
} catch (Exception e) {
Thread.sleep(delay.toMillis());
}Но нужно сохранить последнюю ошибку, если все попытки закончились неудачей:
Exception lastError = null;
Соберём retry в метод:
static <T> T retry(
ThrowingSupplier<T> action,
int attempts,
Duration delay
) throws Exception {
Exception lastError = null;
for (int i = 1; i <= attempts; i++) {
try {
return action.get();
} catch (Exception e) {
lastError = e;
if (i < attempts) {
Thread.sleep(delay.toMillis());
}
}
}
throw lastError;
}
Теперь можно обернуть нестабильную операцию:
String response = retry(
() -> loadFromRemoteApi(),
3,
Duration.ofMillis(300)
);
Если операция сработает со второй или третьей попытки, код продолжит выполнение. Если нет, наружу уйдёт последняя ошибка.
В production-коде к retry часто добавляют экспоненциальную задержку, логирование и ограничение по типам исключений.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3🔥2
Media is too big
VIEW IN TELEGRAM
Java Code Geeks — огромная база туториалов и примеров по Java!
На сайте собраны материалы по Core Java, Java 8/9, concurrency, NIO, logging, design patterns, exceptions, JUnit, Mockito, Spring Boot, Spring MVC, Spring Security, Hibernate, JPA, JDBC, JavaFX и другим темам. Это не одностраничный справочник, а большая база статей и практических примеров: можно листать разделы, открывать конкретные технологии и быстро находить готовые разборы под реальные задачи backend-разработки.
👉 Java Ready | #ресурс
На сайте собраны материалы по Core Java, Java 8/9, concurrency, NIO, logging, design patterns, exceptions, JUnit, Mockito, Spring Boot, Spring MVC, Spring Security, Hibernate, JPA, JDBC, JavaFX и другим темам. Это не одностраничный справочник, а большая база статей и практических примеров: можно листать разделы, открывать конкретные технологии и быстро находить готовые разборы под реальные задачи backend-разработки.
Оставляю ссылочку: Java Code Geeks
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥4
Как сортировать в Java, если в данных бывают null?
Обычная сортировка по полю выглядит просто:
Но если
Например:
Для таких случаев в Comparator есть специальные обёртки:
Теперь null можно отправить в конец:
Результат будет предсказуемым:
Если null нужно поставить в начало, есть nullsFirst:
То же самое удобно для дат, email, optional-полей из базы и данных из внешних API:
Так сортировка явно показывает бизнес-правило: пустые значения не ломают код, а уходят туда, куда нужно.
Если поле для сортировки может быть null, лучше сразу описать это через nullsFirst/nullsLast, а не надеяться, что данные всегда идеальные.
👉 Java Ready | #совет
Обычная сортировка по полю выглядит просто:
users.sort(Comparator.comparing(User::name));
Но если
name() у какого-то пользователя вернёт null, сортировка может упасть с NullPointerException.Например:
record User(String name) {}
var users = new ArrayList<>(List.of(
new User("Bob"),
new User(null),
new User("Ann")
));Для таких случаев в Comparator есть специальные обёртки:
Comparator.nullsLast(String::compareTo)
Теперь null можно отправить в конец:
users.sort(Comparator.comparing(
User::name,
Comparator.nullsLast(String::compareTo)
));
Результат будет предсказуемым:
Ann
Bob
null
Если null нужно поставить в начало, есть nullsFirst:
users.sort(Comparator.comparing(
User::name,
Comparator.nullsFirst(String::compareTo)
));
То же самое удобно для дат, email, optional-полей из базы и данных из внешних API:
orders.sort(Comparator.comparing(
Order::paidAt,
Comparator.nullsLast(Comparator.naturalOrder())
));
Так сортировка явно показывает бизнес-правило: пустые значения не ломают код, а уходят туда, куда нужно.
Если поле для сортировки может быть null, лучше сразу описать это через nullsFirst/nullsLast, а не надеяться, что данные всегда идеальные.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2🔥2
Делаем дедупликацию событий на Java!
Если webhook, очередь или внешний сервис повторно присылает одно и то же событие, бизнес-логика не должна выполняться дважды. Соберём простой обработчик, который запоминает eventId и пропускает дубли.
В этой задаче:
Такой подход помогает избежать повторных списаний, дублей уведомлений и лишней обработки при retry-механиках.
👉 Java Ready | #задача
Если webhook, очередь или внешний сервис повторно присылает одно и то же событие, бизнес-логика не должна выполняться дважды. Соберём простой обработчик, который запоминает eventId и пропускает дубли.
В этой задаче:
• Храним обработанные id в Set;
• Используем add() как проверку на повтор;
• Выполняем действие только для новых событий.
Такой подход помогает избежать повторных списаний, дублей уведомлений и лишней обработки при retry-механиках.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🔥2
Отличная статья про создание собственного Spring Boot 3 starter’а на Java!
В этой статье:
• Как starter превращается в отдельный переиспользуемый блок конфигурации
• Как добавить автоконфигурацию, default-настройки и EnvironmentPostProcessor
• Как собрать стартер и подключить его к обычному Spring Boot-приложению
👉 Java Ready | #статья
В этой статье:
• Как starter превращается в отдельный переиспользуемый блок конфигурации
• Как добавить автоконфигурацию, default-настройки и EnvironmentPostProcessor
• Как собрать стартер и подключить его к обычному Spring Boot-приложению
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Dev.java — ресурс по современной Java!
На сайте собраны материалы от Java-команды: Getting Started, основы языка, Collections Framework, Stream API, Virtual Threads, JShell, инструменты сборки, IDE, новые возможности платформы и отдельные разделы для более глубокого изучения. Хорошо подходит не только новичкам, но и тем, кто хочет освежить современную Java без случайных устаревших примеров.
Оставляю ссылочку: dev.java
👉 Java Ready | #ресурс
На сайте собраны материалы от Java-команды: Getting Started, основы языка, Collections Framework, Stream API, Virtual Threads, JShell, инструменты сборки, IDE, новые возможности платформы и отдельные разделы для более глубокого изучения. Хорошо подходит не только новичкам, но и тем, кто хочет освежить современную Java без случайных устаревших примеров.
Оставляю ссылочку: dev.java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤5🔥5
Делаем простой rate limiter на Java!
Иногда нужно ограничить частоту действий: отправку кода подтверждения, вызов команды, обращение к endpoint или повторную отправку формы. Для базового варианта можно использовать очередь с временем последних успешных вызовов.
В этой задаче:
Такой вариант хорошо подходит для понимания идеи sliding window и небольших локальных сценариев.
👉 Java Ready | #задача
Иногда нужно ограничить частоту действий: отправку кода подтверждения, вызов команды, обращение к endpoint или повторную отправку формы. Для базового варианта можно использовать очередь с временем последних успешных вызовов.
В этой задаче:
• храним timestamps действий;
• удаляем устаревшие записи;
• проверяем размер окна;
Такой вариант хорошо подходит для понимания идеи sliding window и небольших локальных сценариев.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3🔥1
Делаем простой TTL-кэш на Java!
Иногда значение нужно хранить не навсегда, а только короткое время: ответ API, результат вычисления или временную настройку.
Опишем запись кэша:
Создадим хранилище:
Добавим значение с временем жизни:
Теперь достанем значение:
Проверка:
Ожидаемый вывод:
После истечения TTL метод вернёт
👉 Java Ready | #практика
Иногда значение нужно хранить не навсегда, а только короткое время: ответ API, результат вычисления или временную настройку.
Опишем запись кэша:
record Entry<T>(T value, long expiresAt) {}Создадим хранилище:
Map<String, Entry<String>> cache = new HashMap<>();
Добавим значение с временем жизни:
void put(String key, String value, long ttlMs) {
cache.put(key, new Entry<>(
value,
System.currentTimeMillis() + ttlMs
));
}Теперь достанем значение:
String get(String key) {
var entry = cache.get(key);
if (entry == null) {
return null;
}
if (entry.expiresAt() < System.currentTimeMillis()) {
cache.remove(key);
return null;
}
return entry.value();
}Проверка:
put("token", "abc", 1000);
System.out.println(get("token"));Ожидаемый вывод:
abc
После истечения TTL метод вернёт
null, а устаревшая запись удалится из Map.Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥3👎1
Шпаргалка по Maven!
Например, mvn test запускает тесты, mvn package собирает артефакт, а mvn dependency:tree показывает дерево зависимостей проекта.
На картинке основные Maven-команды, фазы lifecycle, полезные параметры командной строки, локальный репозиторий, Maven Central и популярные плагины: help, dependency, compiler, version, wrapper, Spring Boot и exec.
Сохрани, чтобы не потерять!
👉 Java Ready | #ресурс
Например, mvn test запускает тесты, mvn package собирает артефакт, а mvn dependency:tree показывает дерево зависимостей проекта.
На картинке основные Maven-команды, фазы lifecycle, полезные параметры командной строки, локальный репозиторий, Maven Central и популярные плагины: help, dependency, compiler, version, wrapper, Spring Boot и exec.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍6🔥5