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

Автор: @energy_c

Реклама на бирже: https://telega.in/c/java_ready
Download Telegram
Как в Java избежать лишней работы через Optional.orElseGet()?

Optional часто используют, чтобы взять значение или подставить fallback:
String name = userName.orElse(loadDefaultName());


На первый взгляд всё нормально. Но loadDefaultName() выполнится всегда, даже если внутри Optional уже есть значение.

Например:
Optional<String> name = Optional.of("Alice");

String result = name.orElse(expensiveFallback());


expensiveFallback() всё равно будет вызван.

Если fallback дорогой: запрос в базу, чтение файла, HTTP-вызов или тяжёлый расчёт — это лишняя работа.

Для ленивого fallback есть orElseGet():
String result = name.orElseGet(() -> expensiveFallback());


Теперь fallback выполнится только если Optional пустой:
Optional<String> empty = Optional.empty();

String result = empty.orElseGet(() -> expensiveFallback());


Разница особенно заметна в сервисном коде:
User user = cachedUser.orElseGet(() -> loadFromDatabase(id));


Если пользователь уже есть в кэше, база не трогается.

А orElse() лучше оставлять для простых готовых значений:
String label = name.orElse("Anonymous");


Если fallback нужно вычислять, используй orElseGet(). Если значение уже готово то orElse() вполне подходит.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53🔥3
Разбираем Collectors: 7 полезных приёмов для агрегации данных в Java!

Когда нужно не просто пройтись по списку, а сгруппировать элементы, собрать Map, посчитать статистику или подготовить вложенную структуру, обычного map/filter часто уже мало. Эти Collectors помогают писать компактнее и не превращать обработку коллекций в ручные циклы с временными Map и List.

👉 Java Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍42
Напоминалка по concurrent-коллекциям в Java!

Например, ConcurrentHashMap помогает безопасно работать с Map из нескольких потоков, а BlockingQueue удобна для схем producer/consumer.
На картинке шпаргалка по java.util.concurrent: concurrent lists/sets, ConcurrentMap, очереди, BlockingQueue, Deque и основным операциям добавления, удаления и просмотра элементов.

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

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4🔥3
Почему BigDecimal лучше не создавать из double?

BigDecimal часто используют для денег, процентов и точных вычислений:
BigDecimal price = new BigDecimal(0.1);


На первый взгляд всё нормально: хотели получить 0.1.

Но double хранит число в бинарном формате, и многие десятичные дроби там не представляются точно. Поэтому BigDecimal получает не “0.1”, а фактическое значение double.

Это легко увидеть:
System.out.println(new BigDecimal(0.1));


Результат может выглядеть примерно так:
0.100000000000000005551115123125...


Для точных десятичных значений лучше передавать строку:
BigDecimal price = new BigDecimal("0.1");


Или использовать valueOf(), если значение уже пришло как double:
BigDecimal price = BigDecimal.valueOf(0.1);


valueOf() берёт строковое представление double и обычно даёт ожидаемый десятичный результат.

Особенно важно помнить это в расчётах с деньгами:
BigDecimal total = new BigDecimal("19.99")
.multiply(new BigDecimal("3"));


BigDecimal точный, но только если дать ему точное входное значение. Для денег и бизнес-логики не создавай его напрямую из double.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🔥3
Интересная статья про реализацию Spring-подобного API на Java с нуля!

В этой статье:
• Как устроить простые аннотации для описания компонентов
• Как вручную искать классы и создавать объекты
• Как на базовом уровне реализовать идею dependency injection

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


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🔥3
Почему Stream.toList() может сломать старый код?

В 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()
);


👉 Java Ready | #совет
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 | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥5👍4
Делаем простой retry для нестабильной операции в Java!

В реальных приложениях операции иногда падают временно: сеть моргнула, сервис ответил 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 часто добавляют экспоненциальную задержку, логирование и ограничение по типам исключений.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍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 Code Geeks


👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4🔥4
Как сортировать в Java, если в данных бывают null?

Обычная сортировка по полю выглядит просто:
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, а не надеяться, что данные всегда идеальные.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍2🔥2
Делаем дедупликацию событий на Java!

Если webhook, очередь или внешний сервис повторно присылает одно и то же событие, бизнес-логика не должна выполняться дважды. Соберём простой обработчик, который запоминает eventId и пропускает дубли.

В этой задаче:
• Храним обработанные id в Set;
• Используем add() как проверку на повтор;
• Выполняем действие только для новых событий.


Такой подход помогает избежать повторных списаний, дублей уведомлений и лишней обработки при retry-механиках.

👉 Java Ready | #задача
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-приложению

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


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2🔥2