Подборка Telegram каналов для программистов
Системное администрирование 📌
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия. Учи Python быстро и легко🐍
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python Rus
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
https://t.me/books_reserv Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/coddy_academy Полезные советы по программированию
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_1 Статьи из "Хакера"
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Английский 📌
https://t.me/UchuEnglish Английский с нуля
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/tikon_1 Новости высоких технологий, науки и техники💡
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Системное администрирование 📌
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия. Учи Python быстро и легко🐍
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python Rus
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
https://t.me/books_reserv Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/coddy_academy Полезные советы по программированию
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_1 Статьи из "Хакера"
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Английский 📌
https://t.me/UchuEnglish Английский с нуля
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/tikon_1 Новости высоких технологий, науки и техники💡
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Telegram
Девочка Сисадмин
Канал по системному администрированию, который ведет девочка админ. Все о Linux, Windows и т.д.
По всем вопросам : @Sofiia_artamonova
По всем вопросам : @Sofiia_artamonova
❤3🎉1
🚀Разбираем принцип работы ConcurrentHashMap
Сегодня разберёмся, почему
В отличие от
📌 Основные особенности:
- Делит данные на сегменты (до JDK 8 или использует
- Чтение (
- Запись (
- Нет
Пример использования:
А вы часто используете
👉@BookJava
Сегодня разберёмся, почему
ConcurrentHashMap
лучше подходит для многопоточной работы, чем HashMap
, и как он работает внутри. В отличие от
HashMap
, который не потокобезопасен и может приводить к бесконечным циклам при одновременной модификации, ConcurrentHashMap
использует сегментированную блокировку, что позволяет работать с разными частями карты параллельно без полной блокировки всей структуры. 📌 Основные особенности:
- Делит данные на сегменты (до JDK 8 или использует
synchronized
и CAS
операции (начиная с JDK 8).- Чтение (
get()
) не требует блокировки.- Запись (
put()
) использует минимально возможные блокировки.- Нет
null
ключей и значений (в отличие от HashMap
).Пример использования:
import java.util.concurrent.ConcurrentHashMap;
public class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("Java", 1);
map.put("Python", 2);
map.put("C++", 3);
System.out.println(map.get("Java")); // 1
}
}
А вы часто используете
ConcurrentHashMap
? Поделитесь в комментариях! 👇 👉@BookJava
👍11😁1
🚀Как правильно использовать Optional в Java
❌ Плохие примеры:
1️⃣ Использование
Лучше просто использовать
2️⃣ Использование
Лучше так:
📌 Хороший пример использования:
💡 Правильное использование
🔥 А как вы используете
👉@BookJava
Optional<T>
в Java — это мощный инструмент для работы с возможными null
значениями, но часто его используют неправильно. Давайте разберём основные ошибки и лучшие практики. ❌ Плохие примеры:
1️⃣ Использование
Optional
как поля в классе
class User {
Optional<String> name; // ❌ Плохая практика
}
Лучше просто использовать
String
, а если нужно, то оборачивать значение в Optional
при возврате. 2️⃣ Использование
isPresent()
вместо ifPresent()
if (optionalValue.isPresent()) {
process(optionalValue.get()); // ❌ Неоптимально
}
Лучше так:
optionalValue.ifPresent(this::process); // ✅ Правильный подход
📌 Хороший пример использования:
public Optional<User> findUserById(int id) {
return Optional.ofNullable(userRepository.get(id));
}
💡 Правильное использование
Optional
помогает избежать NullPointerException
и делает код чище. 🔥 А как вы используете
Optional
? Пишите в комментариях! 🚀👉@BookJava
👍14🥰3
🔥 Разбираем
Привет, коллеги! Сегодня поговорим о
📌 1. Почему
В Java давно есть
❌ Нельзя комбинировать несколько задач.
❌ Блокирует поток при вызове
❌ Нет удобных методов для обработки результатов.
👉
📌 2. Базовый пример использования
🔹 Здесь
📌 3. Комбинирование нескольких задач
✅
📌 4. Обработка ошибок (
✅ Если в
📌 5. Запуск нескольких задач параллельно
✅
📌 Итог
🔹
🔹 Позволяет избежать блокировок, обрабатывать ошибки, комбинировать задачи.
🔹 Улучшает читаемость кода по сравнению с
📢 А как вы используете
👉@BookJava
CompletableFuture
: Асинхронность в Java без боли Привет, коллеги! Сегодня поговорим о
CompletableFuture
, который помогает писать асинхронный код в Java без коллбэков и потерь в читабельности. 📌 1. Почему
CompletableFuture
? В Java давно есть
Future
, но он неудобен: ❌ Нельзя комбинировать несколько задач.
❌ Блокирует поток при вызове
.get()
. ❌ Нет удобных методов для обработки результатов.
👉
CompletableFuture
решает все эти проблемы, позволяя комбинировать задачи, обрабатывать ошибки и не блокировать потоки.📌 2. Базовый пример использования
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Привет, мир!";
});
future.thenAccept(result -> System.out.println("Результат: " + result));
System.out.println("Этот текст выведется раньше результата!");
sleep(3000); // Чтобы программа не завершилась раньше времени
}
private static void sleep(int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
}
}
🔹 Здесь
supplyAsync()
выполняет задачу в другом потоке, а thenAccept()
позволяет асинхронно обработать результат. 📌 3. Комбинирование нескольких задач
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
System.out.println(result.join()); // Hello World
✅
thenCombine()
объединяет результаты двух асинхронных задач. 📌 4. Обработка ошибок (
exceptionally
)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("Что-то пошло не так!");
}
return "Все хорошо!";
}).exceptionally(ex -> "Ошибка: " + ex.getMessage());
System.out.println(future.join());
✅ Если в
supplyAsync()
произошла ошибка, она обработается в exceptionally()
, и программа не упадёт. 📌 5. Запуск нескольких задач параллельно
CompletableFuture<Void> allTasks = CompletableFuture.allOf(
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 1", 1000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 2", 2000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 3", 1500))
);
allTasks.join(); // Дождёмся завершения всех задач
private static void sleepAndPrint(String msg, int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
System.out.println(msg);
}
✅
allOf()
позволяет запустить несколько задач параллельно и дождаться их завершения. 📌 Итог
🔹
CompletableFuture
– это мощный инструмент для работы с асинхронностью в Java. 🔹 Позволяет избежать блокировок, обрабатывать ошибки, комбинировать задачи.
🔹 Улучшает читаемость кода по сравнению с
Future
и ExecutorService
. 📢 А как вы используете
CompletableFuture
в своих проектах? Делитесь в комментариях! 🚀 👉@BookJava
👍13❤5
1️⃣ Чем
В Java 14 появился
🔹 Запись против класса
Обычный класс:
Много бойлерплейта…
Теперь то же самое с
✅ Меньше кода
✅ Автоматически генерируются
✅ Иммутабельность по умолчанию
⚠️ Когда НЕ стоит использовать
- Если нужен изменяемый объект
- Если требуется сложная бизнес-логика внутри класса
Вы уже используете
👉@BookJava
record
лучше class
в Java? В Java 14 появился
record
– новый тип классов, предназначенный для удобного хранения данных. Чем он лучше обычного class
? Давайте разберёмся! 🔹 Запись против класса
Обычный класс:
class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
Много бойлерплейта…
Теперь то же самое с
record
:
record Person(String name, int age) {}
✅ Меньше кода
✅ Автоматически генерируются
toString()
, equals()
, hashCode()
✅ Иммутабельность по умолчанию
⚠️ Когда НЕ стоит использовать
record
? - Если нужен изменяемый объект
- Если требуется сложная бизнес-логика внутри класса
Вы уже используете
record
в своих проектах? Делитесь опытом! 🚀 👉@BookJava
👍9
На открытом вебинаре «Resilience4j. Bulkhead» вы узнаете, как защитить свои сервисы от сбоев. Разберём ключевые возможности Bulkhead и покажем, как ограничение ресурсов может спасти приложение.
Хотите углубить навыки бэкенд-разработки, повысить устойчивость своих микросервисов и освоить Resilience4j?
🗓 Всё это уже 12 февраля в 20:00 мск!
Спикер Сергей Петрелевич — опытный разработчик на Java и Kotlin.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
2️⃣ Что нового в Java 21? ТОП-5 фич, которые стоит знать
Java 21 – это LTS-релиз, который принесёт важные улучшения. Вот самые интересные новинки:
1️⃣ Виртуальные потоки (Virtual Threads) 🧵
- Теперь
- Создание тысячи потоков стало дешёвым и быстрым:
2️⃣ Pattern Matching для
- Больше не нужно кастовать вручную!
3️⃣ Scoped Values (Альтернатива
- Теперь передача данных в потоки стала безопаснее!
4️⃣ Record Patterns
- Улучшенный
5️⃣ String Templates (в превью!)
- Упрощённое создание строк:
Java 21 делает язык ещё удобнее! Какая фича понравилась больше всего? 🤔
👉@BookJava
Java 21 – это LTS-релиз, который принесёт важные улучшения. Вот самые интересные новинки:
1️⃣ Виртуальные потоки (Virtual Threads) 🧵
- Теперь
Thread
больше не проблема! - Создание тысячи потоков стало дешёвым и быстрым:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("Hello, Virtual Thread!"));
}
2️⃣ Pattern Matching для
switch
- Больше не нужно кастовать вручную!
static void test(Object obj) {
switch (obj) {
case String s -> System.out.println("Это строка: " + s);
case Integer i when i > 0 -> System.out.println("Положительное число: " + i);
default -> System.out.println("Что-то другое");
}
}
3️⃣ Scoped Values (Альтернатива
ThreadLocal
) - Теперь передача данных в потоки стала безопаснее!
static final ScopedValue<String> USER = ScopedValue.newInstance();
ScopedValue.runWhere(USER, "Admin", () -> System.out.println(USER.get()));
4️⃣ Record Patterns
- Улучшенный
record
, теперь можно удобно распаковывать данные:
record Point(int x, int y) {}
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("Координаты: " + x + ", " + y);
}
}
5️⃣ String Templates (в превью!)
- Упрощённое создание строк:
String name = "Alice";
String message = STR."Привет, \{name}!";
Java 21 делает язык ещё удобнее! Какая фича понравилась больше всего? 🤔
👉@BookJava
👍9🔥7🥰4
🔥 5 паттернов проектирования, которые должен знать каждый Java-разработчик
В мире Java есть сотни паттернов проектирования, но эти 5 используются чаще всего. Если вы их освоите, ваш код станет чище, гибче и легче в поддержке.
1️⃣ Singleton
Ограничивает создание объекта одним экземпляром. Полезен для логирования, работы с базами данных, кэшей.
🔹 Пример кода (Lazy Initialization, thread-safe):
⚡ Используется в Spring Bean, Hibernate SessionFactory.
2️⃣ Factory Method
Позволяет создавать объекты без привязки к конкретному классу. Отлично подходит, если у вас много типов объектов с общей логикой.
🔹 Пример:
⚡ Используется в JDBC (DriverManager.getConnection).
3️⃣ Builder
Позволяет создавать сложные объекты пошагово. Альтернатива длинным конструкторам с кучей параметров.
🔹 Пример (Lombok
⚡ Используется в StringBuilder, HttpRequest в Java 11+.
4️⃣ Observer
Позволяет подписаться на события и реагировать на них. Часто используется в GUI, event-driven системах.
🔹 Пример (наблюдатель за событиями):
⚡ Используется в Spring Events, RxJava.
5️⃣ Decorator
Добавляет функциональность объекту без изменения его структуры. Часто применяется в логгировании, кешировании, потоках IO.
🔹 Пример (логирование обертки над OutputStream):
⚡ Используется в BufferedReader, Logger, Spring Security Filters.
💬 Ну и в заключение
Если вы хотите писать гибкий и масштабируемый код, обязательно используйте паттерны проектирования. А какие из них вы используете в своих проектах чаще всего? Делитесь в комментариях! 🚀
👉@BookJava
В мире Java есть сотни паттернов проектирования, но эти 5 используются чаще всего. Если вы их освоите, ваш код станет чище, гибче и легче в поддержке.
1️⃣ Singleton
Ограничивает создание объекта одним экземпляром. Полезен для логирования, работы с базами данных, кэшей.
🔹 Пример кода (Lazy Initialization, thread-safe):
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
⚡ Используется в Spring Bean, Hibernate SessionFactory.
2️⃣ Factory Method
Позволяет создавать объекты без привязки к конкретному классу. Отлично подходит, если у вас много типов объектов с общей логикой.
🔹 Пример:
interface Product {
void create();
}
class ConcreteProductA implements Product {
public void create() { System.out.println("Создан продукт A"); }
}
class ProductFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) return new ConcreteProductA();
throw new IllegalArgumentException("Неизвестный тип продукта");
}
}
⚡ Используется в JDBC (DriverManager.getConnection).
3️⃣ Builder
Позволяет создавать сложные объекты пошагово. Альтернатива длинным конструкторам с кучей параметров.
🔹 Пример (Lombok
@Builder
делает его проще!):
@Builder
public class Car {
private String model;
private int year;
private String engine;
}
Car car = Car.builder().model("Tesla").year(2024).engine("Electric").build();
⚡ Используется в StringBuilder, HttpRequest в Java 11+.
4️⃣ Observer
Позволяет подписаться на события и реагировать на них. Часто используется в GUI, event-driven системах.
🔹 Пример (наблюдатель за событиями):
interface Observer {
void update(String message);
}
class User implements Observer {
private String name;
public User(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " получил уведомление: " + message);
}
}
class Channel {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer o) { observers.add(o); }
public void notifyAll(String message) {
for (Observer o : observers) { o.update(message); }
}
}
⚡ Используется в Spring Events, RxJava.
5️⃣ Decorator
Добавляет функциональность объекту без изменения его структуры. Часто применяется в логгировании, кешировании, потоках IO.
🔹 Пример (логирование обертки над OutputStream):
class LoggingOutputStream extends OutputStream {
private OutputStream wrapped;
public LoggingOutputStream(OutputStream wrapped) { this.wrapped = wrapped; }
@Override
public void write(int b) throws IOException {
System.out.println("Записываем байт: " + b);
wrapped.write(b);
}
}
⚡ Используется в BufferedReader, Logger, Spring Security Filters.
💬 Ну и в заключение
Если вы хотите писать гибкий и масштабируемый код, обязательно используйте паттерны проектирования. А какие из них вы используете в своих проектах чаще всего? Делитесь в комментариях! 🚀
👉@BookJava
👍11🥰4🏆4❤1
🚀 Stream API в Java: 5 мощных трюков, которые ты мог не знать
Stream API – одна из самых крутых фич в Java, но многие используют только
🔹 1. Группировка элементов (
Разбиваем список строк на группы по длине:
🔹 2. Уникальные элементы (
Фильтруем дубликаты в потоке:
🔹 3. Пропуск N элементов (
Хотим пропустить первые 3 элемента и взять только оставшиеся:
🔹 4. Найти максимальное значение (
Допустим, у нас есть список чисел, найдем максимальное:
🔹 5. Проверить, содержит ли список нужное значение (
Допустим, нам нужно проверить, есть ли в списке число больше 100:
🔥 Stream API – это мощный инструмент для работы с коллекциями. Используйте его, и ваш код станет чище, короче и быстрее!
А какие крутые трюки со стримами знаете вы? Делитесь в комментариях! 👇
👉@BookJava
Stream API – одна из самых крутых фич в Java, но многие используют только
map()
, filter()
и collect()
. Давай разберем 5 полезных трюков, которые сделают код элегантнее и эффективнее! 🔹 1. Группировка элементов (
Collectors.groupingBy
) Разбиваем список строк на группы по длине:
List<String> words = List.of("apple", "banana", "cat", "dog", "elephant");
Map<Integer, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(grouped);
// {3=[cat, dog], 5=[apple], 6=[banana], 8=[elephant]}
🔹 2. Уникальные элементы (
distinct()
) Фильтруем дубликаты в потоке:
List<Integer> numbers = List.of(1, 2, 2, 3, 4, 4, 5);
List<Integer> unique = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(unique); // [1, 2, 3, 4, 5]
🔹 3. Пропуск N элементов (
skip(n)
) Хотим пропустить первые 3 элемента и взять только оставшиеся:
List<String> names = List.of("Alice", "Bob", "Charlie", "David", "Eve");
List<String> skipped = names.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(skipped); // [David, Eve]
🔹 4. Найти максимальное значение (
max()
) Допустим, у нас есть список чисел, найдем максимальное:
List<Integer> nums = List.of(10, 20, 30, 5, 15);
Optional<Integer> maxNum = nums.stream().max(Integer::compareTo);
maxNum.ifPresent(System.out::println); // 30
🔹 5. Проверить, содержит ли список нужное значение (
anyMatch()
) Допустим, нам нужно проверить, есть ли в списке число больше 100:
List<Integer> nums = List.of(10, 50, 200, 30);
boolean hasLargeNumber = nums.stream().anyMatch(n -> n > 100);
System.out.println(hasLargeNumber); // true
🔥 Stream API – это мощный инструмент для работы с коллекциями. Используйте его, и ваш код станет чище, короче и быстрее!
А какие крутые трюки со стримами знаете вы? Делитесь в комментариях! 👇
👉@BookJava
👍16🎉1
🔹 Разбираем Lombok: как избавиться от шаблонного кода
Ты всё ещё пишешь getters и setters вручную? Используй Lombok!
💡 Как подключить?
Добавь в pom.xml:
💡 Как использовать?
Теперь getName(), setName() и toString() сгенерируются автоматически!
👉 Lombok. Полное руководство
https://auth0.com/blog/a-complete-guide-to-lombok/
Кто уже использует Lombok в своих проектах?
👉@BookJava
Ты всё ещё пишешь getters и setters вручную? Используй Lombok!
💡 Как подключить?
Добавь в pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
💡 Как использовать?
import lombok.Data;
@Data
public class User {
private String name;
private int age;
}
Теперь getName(), setName() и toString() сгенерируются автоматически!
👉 Lombok. Полное руководство
https://auth0.com/blog/a-complete-guide-to-lombok/
Кто уже использует Lombok в своих проектах?
👉@BookJava
👍5👎1
📌 Record vs Class в Java – когда что использовать?
👋 Сегодня разберёмся с record и class в Java. Когда лучше использовать record, а когда стоит остаться на классах?
🧐 Что такое
Record — это специальный тип класса, предназначенный для хранения неизменяемых данных. Он автоматически генерирует:
✅ Конструктор, принимающий все поля
✅
✅ Методы доступа (`getter'ы`)
📌 Пример использования Record:
🔥 Это равнозначно следующему классу:
🏆 Когда использовать
✔️ Когда у вас неизменяемые (immutable) объекты
✔️ Когда вам нужны только данные без логики
✔️ Когда хочется избежать бойлерплейта
⛔ Когда НЕ стоит использовать
🚫 Если нужно наследование (record не поддерживает `extends`)
🚫 Если объект должен быть мутабельным (изменяемым)
🚫 Если в классе должна быть сложная логика поведения
✍️ Итог
Используйте record, если вам нужен простой DTO (Data Transfer Object) без лишнего кода. Но если у объекта есть логика, стоит оставить класс.
👉@BookJava
👋 Сегодня разберёмся с record и class в Java. Когда лучше использовать record, а когда стоит остаться на классах?
🧐 Что такое
record
? Record — это специальный тип класса, предназначенный для хранения неизменяемых данных. Он автоматически генерирует:
✅ Конструктор, принимающий все поля
✅
toString()
, equals()
, hashCode()
✅ Методы доступа (`getter'ы`)
📌 Пример использования Record:
public record User(String name, int age) {}
🔥 Это равнозначно следующему классу:
public final class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
@Override
public boolean equals(Object o) { /* реализация */ }
@Override
public int hashCode() { /* реализация */ }
@Override
public String toString() { /* реализация */ }
}
🏆 Когда использовать
record
? ✔️ Когда у вас неизменяемые (immutable) объекты
✔️ Когда вам нужны только данные без логики
✔️ Когда хочется избежать бойлерплейта
⛔ Когда НЕ стоит использовать
record
? 🚫 Если нужно наследование (record не поддерживает `extends`)
🚫 Если объект должен быть мутабельным (изменяемым)
🚫 Если в классе должна быть сложная логика поведения
✍️ Итог
Используйте record, если вам нужен простой DTO (Data Transfer Object) без лишнего кода. Но если у объекта есть логика, стоит оставить класс.
👉@BookJava
👍6
📌 Java Record: Почему Это Круто?
Сегодня расскажу вам о record в Java – мощном инструменте, который упростит вашу жизнь при работе с неизменяемыми объектами.
🔹 Что такое record?
Введённый в Java 14,
✅ Конструктор
✅ Геттеры (но без
✅
🔹 Пример использования
Этот код эквивалентен написанию полноценного класса с полями, конструктором, геттерами и методами
🔹 Преимущества record
🚀 Меньше кода – никаких бойлерплейтов
🚀 Иммутабельность – данные не изменяются после создания
🚀 Читаемость – сразу видно, что это объект только для хранения данных
🔹 Ограничения:
❗ Поля
❗ Наследование от
👉@BookJava
Сегодня расскажу вам о record в Java – мощном инструменте, который упростит вашу жизнь при работе с неизменяемыми объектами.
🔹 Что такое record?
Введённый в Java 14,
record
– это специальный тип класса, предназначенный для хранения данных. Он автоматически генерирует: ✅ Конструктор
✅ Геттеры (но без
get
в названии) ✅
equals()
, hashCode()
, toString()
🔹 Пример использования
public record User(String name, int age) {}
Этот код эквивалентен написанию полноценного класса с полями, конструктором, геттерами и методами
equals/hashCode/toString
, но занимает всего одну строку! 🔹 Преимущества record
🚀 Меньше кода – никаких бойлерплейтов
🚀 Иммутабельность – данные не изменяются после создания
🚀 Читаемость – сразу видно, что это объект только для хранения данных
🔹 Ограничения:
❗ Поля
record
всегда final ❗ Наследование от
record
запрещено 👉@BookJava
👍10
Совет Spring Framework💡
Вы можете автосопрягать несколько бинов, реализующих определенный интерфейс, в список, содержащий все реализации. Определите список с общим типом, который вы хотите использовать. Вы можете использовать инъекцию конструктора, как показано на картинке, или инъекцию поля.
👉@BookJava
Вы можете автосопрягать несколько бинов, реализующих определенный интерфейс, в список, содержащий все реализации. Определите список с общим типом, который вы хотите использовать. Вы можете использовать инъекцию конструктора, как показано на картинке, или инъекцию поля.
👉@BookJava
👍8
Блокировки в HotSpot JVM
Java Virtual Machine (JVM) — это промежуточное звено между скомпилированным Java-кодом и операционной системой (ОС). Благодаря этому механизму Java-приложения можно запускать на разных платформах без модификаций. Существует множество реализаций JVM, но наиболее популярной является HotSpot, входящая в состав OpenJDK.
Однако JVM не просто транслирует Java-код в инструкции ОС. Она включает в себя множество оптимизаций, позволяющих исполнять код быстрее и эффективнее. Одна из таких оптимизаций касается механизма блокировок (synchronization locks).
Виды блокировок в HotSpot
Виртуальная машина HotSpot использует три вида блокировок в зависимости от уровня конкуренции между потоками:
1️⃣ Fat Lock (Inflated Lock) — классическая блокировка на основе мониторов объектов (mutexes). Этот метод используется, когда большое количество потоков одновременно пытаются захватить блокировку.
2️⃣ Thin Lock (Deflated Lock) — облегчённая блокировка, использующая атомарные CAS-операции (Compare-And-Swap). Такой подход быстрее мьютексов, но становится неэффективным при высоком уровне конкуренции, поскольку требует эксклюзивного доступа.
3️⃣ Biased Lock — предвзятая блокировка, предназначенная для сценариев, в которых объект используется одним и тем же потоком. При первом взаимодействии объект привязывается к потоку, и последующие операции с ним выполняются без затрат на синхронизацию. Однако, если другой поток попытается захватить блокировку, произойдёт глобальная аннулирование (bulk revocation), что может привести к значительным накладным расходам.
> Важно! Biased Lock по умолчанию отключён при запуске JVM, поскольку на старте приложения активно взаимодействуют множество потоков. Через некоторое время он автоматически включается и становится основной стратегией блокировки.
Тонкая настройка JVM
JVM позволяет управлять стратегией блокировок с помощью следующих параметров:
- Отключение Biased Lock
- Регулировка времени включения Biased Lock (по умолчанию 4 сек)
Здесь
Когда настраивать блокировки вручную?
В большинстве приложений не требуется изменять эти параметры, так как JVM автоматически выбирает оптимальные стратегии. Однако в высоконагруженных сценариях, например в паттерне Producer-Consumer, правильная настройка блокировок может значительно повысить производительность.
Если ваше приложение испытывает проблемы с блокировками, профилирование с помощью JVM TI, JFR (Java Flight Recorder) или perf поможет выявить узкие места и подобрать наиболее подходящий метод синхронизации.
👉@BookJava
Java Virtual Machine (JVM) — это промежуточное звено между скомпилированным Java-кодом и операционной системой (ОС). Благодаря этому механизму Java-приложения можно запускать на разных платформах без модификаций. Существует множество реализаций JVM, но наиболее популярной является HotSpot, входящая в состав OpenJDK.
Однако JVM не просто транслирует Java-код в инструкции ОС. Она включает в себя множество оптимизаций, позволяющих исполнять код быстрее и эффективнее. Одна из таких оптимизаций касается механизма блокировок (synchronization locks).
Виды блокировок в HotSpot
Виртуальная машина HotSpot использует три вида блокировок в зависимости от уровня конкуренции между потоками:
1️⃣ Fat Lock (Inflated Lock) — классическая блокировка на основе мониторов объектов (mutexes). Этот метод используется, когда большое количество потоков одновременно пытаются захватить блокировку.
2️⃣ Thin Lock (Deflated Lock) — облегчённая блокировка, использующая атомарные CAS-операции (Compare-And-Swap). Такой подход быстрее мьютексов, но становится неэффективным при высоком уровне конкуренции, поскольку требует эксклюзивного доступа.
3️⃣ Biased Lock — предвзятая блокировка, предназначенная для сценариев, в которых объект используется одним и тем же потоком. При первом взаимодействии объект привязывается к потоку, и последующие операции с ним выполняются без затрат на синхронизацию. Однако, если другой поток попытается захватить блокировку, произойдёт глобальная аннулирование (bulk revocation), что может привести к значительным накладным расходам.
> Важно! Biased Lock по умолчанию отключён при запуске JVM, поскольку на старте приложения активно взаимодействуют множество потоков. Через некоторое время он автоматически включается и становится основной стратегией блокировки.
Тонкая настройка JVM
JVM позволяет управлять стратегией блокировок с помощью следующих параметров:
- Отключение Biased Lock
-XX:-UseBiasedLocking
- Регулировка времени включения Biased Lock (по умолчанию 4 сек)
-XX:BiasedLockingStartupDelay=500
Здесь
500
указывает задержку в миллисекундах. Когда настраивать блокировки вручную?
В большинстве приложений не требуется изменять эти параметры, так как JVM автоматически выбирает оптимальные стратегии. Однако в высоконагруженных сценариях, например в паттерне Producer-Consumer, правильная настройка блокировок может значительно повысить производительность.
Если ваше приложение испытывает проблемы с блокировками, профилирование с помощью JVM TI, JFR (Java Flight Recorder) или perf поможет выявить узкие места и подобрать наиболее подходящий метод синхронизации.
👉@BookJava
👍5❤1👎1
🚀 Разбираемся с
Сегодня разберёмся с
✅ Когда
1️⃣ Сокращение шаблонного кода
2️⃣ Улучшает читаемость при длинных объявлениях
3️⃣ Хорош при использовании анонимных классов
4️⃣ Идеален для итераторов
❌ Когда
1️⃣ Неочевидный тип данных
2️⃣ Снижение читаемости сложного кода
3️⃣ Не подходит для публичных API
Если метод возвращает
🔥 Итог
Используйте
📌26 рекомендаций по использованию типа var в Java
https://habr.com/ru/articles/438206/
https://dzone.com/articles/var-work-in-progress
👉@BookJava
var
в Java: Когда использовать, а когда нет? Сегодня разберёмся с
var
в Java. Этот локальный тип вывода переменной появился в Java 10 и сразу вызвал много споров. Давайте посмотрим, когда его стоит использовать, а когда лучше отказаться. ✅ Когда
var
полезен? 1️⃣ Сокращение шаблонного кода
var list = new ArrayList<String>(); // читается проще
2️⃣ Улучшает читаемость при длинных объявлениях
var map = new HashMap<String, List<Integer>>();
3️⃣ Хорош при использовании анонимных классов
var thread = new Thread(() -> System.out.println("Hello"));
4️⃣ Идеален для итераторов
for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
❌ Когда
var
ухудшает код? 1️⃣ Неочевидный тип данных
var data = fetchData(); // Что вернет метод? Интуитивно непонятно!
2️⃣ Снижение читаемости сложного кода
var something = doSomethingComplicated(); // А что это такое?
3️⃣ Не подходит для публичных API
Если метод возвращает
var
, мы теряем контракт с пользователем API.🔥 Итог
Используйте
var
, когда тип очевиден и код становится чище. Не злоупотребляйте им, чтобы не терять читаемость! 📌26 рекомендаций по использованию типа var в Java
https://habr.com/ru/articles/438206/
https://dzone.com/articles/var-work-in-progress
👉@BookJava
👍17👎2👏2
📌 Паттерн "Одиночка" (Singleton) – когда и как правильно использовать?
👋 Сегодня хочу поговорить о Singleton – одном из самых популярных (и часто злоупотребляемых) паттернов в Java.
🔥 Что такое Singleton?
Singleton гарантирует, что у класса будет только один экземпляр и предоставляет глобальную точку доступа к нему.
Пример классического Singleton:
Здесь используется жадная инициализация – объект создаётся сразу при загрузке класса.
💣 Проблемы Singleton
1️⃣ Нарушение SRP (Single Responsibility Principle) – Singleton управляет своим жизненным циклом.
2️⃣ Проблемы с тестированием – сложность мокирования в юнит-тестах.
3️⃣ Глобальное состояние – сложнее поддерживать код, возможны неожиданные баги.
✅ Когда использовать Singleton?
✔ Если требуется единый точный экземпляр (например, пул соединений, логгер).
✔ Если объект дорого создавать и его состояние неизменно.
✔ Когда глобальная точка доступа действительно оправдана.
🔧 Альтернативы
👉 Dependency Injection (DI) – лучше передавать объект через конструктор.
👉 Enum Singleton – лучший способ создать потокобезопасный Singleton:
Он защищён от сериализации и reflection-атак! 🚀
👉@BookJava
👋 Сегодня хочу поговорить о Singleton – одном из самых популярных (и часто злоупотребляемых) паттернов в Java.
🔥 Что такое Singleton?
Singleton гарантирует, что у класса будет только один экземпляр и предоставляет глобальную точку доступа к нему.
Пример классического Singleton:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
Здесь используется жадная инициализация – объект создаётся сразу при загрузке класса.
💣 Проблемы Singleton
1️⃣ Нарушение SRP (Single Responsibility Principle) – Singleton управляет своим жизненным циклом.
2️⃣ Проблемы с тестированием – сложность мокирования в юнит-тестах.
3️⃣ Глобальное состояние – сложнее поддерживать код, возможны неожиданные баги.
✅ Когда использовать Singleton?
✔ Если требуется единый точный экземпляр (например, пул соединений, логгер).
✔ Если объект дорого создавать и его состояние неизменно.
✔ Когда глобальная точка доступа действительно оправдана.
🔧 Альтернативы
👉 Dependency Injection (DI) – лучше передавать объект через конструктор.
👉 Enum Singleton – лучший способ создать потокобезопасный Singleton:
public enum SingletonEnum {
INSTANCE;
public void someMethod() {
System.out.println("Работаем!");
}
}
Он защищён от сериализации и reflection-атак! 🚀
👉@BookJava
👍10
🚀 Apache Kafka и Spring — лучшие друзья микросервисов! Хотите узнать, почему?
На открытом уроке мы покажем, как объединить Kafka и Spring Framework для создания масштабируемых и надежных систем. В теории и практике!
🔍 Вы научитесь:
- Настраивать асинхронное взаимодействие
- Обрабатывать сообщения в реальном времени
- Использовать инструменты мониторинга для оптимизации работы микросервисов
🗓 Занятие пройдет 18 февраля в 20:00 МСК и будет приурочено к старту курса «Apache Kafka». После урока вы сможете продолжить обучение по специальной цене и даже в рассрочку!
👉 Забронируйте свое место на открытом уроке! Пройдите короткий тест и получите запись: https://vk.cc/cIGdPJ
На открытом уроке мы покажем, как объединить Kafka и Spring Framework для создания масштабируемых и надежных систем. В теории и практике!
🔍 Вы научитесь:
- Настраивать асинхронное взаимодействие
- Обрабатывать сообщения в реальном времени
- Использовать инструменты мониторинга для оптимизации работы микросервисов
🗓 Занятие пройдет 18 февраля в 20:00 МСК и будет приурочено к старту курса «Apache Kafka». После урока вы сможете продолжить обучение по специальной цене и даже в рассрочку!
👉 Забронируйте свое место на открытом уроке! Пройдите короткий тест и получите запись: https://vk.cc/cIGdPJ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 5 полезных библиотек для Java-разработчика
🔹 Lombok – убирает бойлерплейт-код. Автоматически генерирует геттеры, сеттеры, конструкторы,
🔹 Guava – коллекции, кэширование, строки, примитивные типы, функциональные утилиты и многое другое. Разработана Google, широко используется в индустрии.
🔹 Apache Commons – набор утилит для работы со строками, коллекциями, потоками, датами. Позволяет сократить код и улучшить его читаемость.
🔹 Jackson – одна из лучших библиотек для работы с JSON. Позволяет сериализовать и десериализовать Java-объекты быстро и без лишнего кода.
🔹 Junit + Mockito – тестирование в Java. JUnit – основной инструмент для написания юнит-тестов, а Mockito помогает мокировать зависимости и тестировать сложные сценарии.
👉@BookJava
🔹 Lombok – убирает бойлерплейт-код. Автоматически генерирует геттеры, сеттеры, конструкторы,
toString()
, equals()
, hashCode()
. Больше не нужно писать однотипный код вручную! 🔹 Guava – коллекции, кэширование, строки, примитивные типы, функциональные утилиты и многое другое. Разработана Google, широко используется в индустрии.
🔹 Apache Commons – набор утилит для работы со строками, коллекциями, потоками, датами. Позволяет сократить код и улучшить его читаемость.
🔹 Jackson – одна из лучших библиотек для работы с JSON. Позволяет сериализовать и десериализовать Java-объекты быстро и без лишнего кода.
🔹 Junit + Mockito – тестирование в Java. JUnit – основной инструмент для написания юнит-тестов, а Mockito помогает мокировать зависимости и тестировать сложные сценарии.
👉@BookJava
👍12🔥4😁1
Что спрашивают на собеседовании у Middle Java-разработчика?
Уже завтра, 19 февраля в 19:00 мск — бесплатное открытое собеседование в прямом эфире!
Интервьюер Илья Аров с опытом работы в крупных банках задаст реальные вопросы разработчику-добровольцу и разберёт его ответы. В конце — время вопросов ментору из зала.
Что узнаешь на эфире:
✅ Какие вопросы задают на собеседованиях и зачем
✅ Как подготовиться, чтобы получить достойный оффер
✅ Чего ждут от кандидатов на Middle Java
Запишись на эфир в боте ШОРТКАТ → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqw2cVob
Уже завтра, 19 февраля в 19:00 мск — бесплатное открытое собеседование в прямом эфире!
Интервьюер Илья Аров с опытом работы в крупных банках задаст реальные вопросы разработчику-добровольцу и разберёт его ответы. В конце — время вопросов ментору из зала.
Что узнаешь на эфире:
✅ Какие вопросы задают на собеседованиях и зачем
✅ Как подготовиться, чтобы получить достойный оффер
✅ Чего ждут от кандидатов на Middle Java
Запишись на эфир в боте ШОРТКАТ → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqw2cVob
@Hibernate
можно использовать только для отношений, но не для простых (базовых) атрибутов. Чтобы она работала и для полей, необходимо использовать байткод-энхансмент через плагин. В этом случае поля, отмеченные как
lazy
, будут загружаться при первом обращении к ним.#Java #JPA
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Работа с временными метками в Java: что нужно знать?
Всем раннего утра! 👋 Сегодня разберём важную тему — работу с временными метками в Java. Это может пригодиться при логировании, кэшировании, обработке данных и даже в повседневных задачах.
1. Получение текущей временной метки
В Java с появлением
Значение
2. Преобразование timestamp в дату и время
Допустим, у нас есть временная метка, и нам нужно преобразовать её в локальное время:
Так можно легко получить читабельную дату.
3. Разница между датами
Вычислить разницу между двумя временными метками можно так:
Отличный способ измерять производительность кода!
4. Форматирование и вывод даты
Для вывода даты в удобочитаемом формате используем
Итог
Работа с временными метками в Java теперь проще, чем когда-либо. Используйте
👉@BookJava
Всем раннего утра! 👋 Сегодня разберём важную тему — работу с временными метками в Java. Это может пригодиться при логировании, кэшировании, обработке данных и даже в повседневных задачах.
1. Получение текущей временной метки
В Java с появлением
java.time
всё стало проще. Самый удобный способ получить timestamp:
Instant instant = Instant.now();
long timestamp = instant.toEpochMilli(); // В миллисекундах
Значение
timestamp
соответствует количеству миллисекунд, прошедших с 1 января 1970 года (UTC).2. Преобразование timestamp в дату и время
Допустим, у нас есть временная метка, и нам нужно преобразовать её в локальное время:
long timestamp = 1700000000000L; // Пример временной метки
Instant instant = Instant.ofEpochMilli(timestamp);
ZonedDateTime dateTime = instant.atZone(ZoneId.systemDefault());
System.out.println(dateTime);
Так можно легко получить читабельную дату.
3. Разница между датами
Вычислить разницу между двумя временными метками можно так:
Instant start = Instant.now();
Thread.sleep(2000); // Эмуляция задержки
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("Разница в секундах: " + duration.getSeconds());
Отличный способ измерять производительность кода!
4. Форматирование и вывод даты
Для вывода даты в удобочитаемом формате используем
DateTimeFormatter
:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
String formatted = dateTime.format(formatter);
System.out.println(formatted);
Итог
Работа с временными метками в Java теперь проще, чем когда-либо. Используйте
Instant
, Duration
и DateTimeFormatter
для удобного управления временем. 👉@BookJava
🎉5👍4