10986
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP
💡Совет: по умолчанию ленивую загрузку в @Hibernate можно использовать только для отношений, но не для простых (базовых) атрибутов.
Чтобы она работала и для полей, необходимо использовать байткод-энхансмент через плагин. В этом случае поля, отмеченные как lazy, будут загружаться при первом обращении к ним.
#Java #JPA
📲 Мы в MAX
👉@BookJava
📌 Паттерн "Одиночка" (Singleton) – когда и как правильно использовать?
👋 Сегодня хочу поговорить о Singleton – одном из самых популярных (и часто злоупотребляемых) паттернов в Java.
🔥 Что такое Singleton?
Singleton гарантирует, что у класса будет только один экземпляр и предоставляет глобальную точку доступа к нему.
Пример классического Singleton:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
public enum SingletonEnum {
INSTANCE;
public void someMethod() {
System.out.println("Работаем!");
}
}
⁉️ API описано, но команда всё равно понимает его по-разному? Документация устаревает, интеграции ломаются, а согласование занимает больше времени, чем разработка?
👩💻Приглашаем на открытый урок «OpenAPI + Spring»
🗓 15 апреля в 20:00 МСК
🆓 На открытом уроке разберём, как OpenAPI помогает навести порядок: от генерации спецификаций до интеграции в приложения на Spring. Покажем, как сократить количество ошибок, упростить взаимодействие между командами и сделать разработку предсказуемой. Разберём реальные сценарии: где возникают проблемы, как их избежать и какие подходы работают в проектах.
Урок будет полезен разработчикам, архитекторам и всем, кто работает с API.
🔗 Ссылка на регистрацию: https://vk.cc/cWnqAQ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
📌 Java Record: Почему Это Круто?
Сегодня расскажу вам о record в Java – мощном инструменте, который упростит вашу жизнь при работе с неизменяемыми объектами.
🔹 Что такое record?
Введённый в Java 14, record – это специальный тип класса, предназначенный для хранения данных. Он автоматически генерирует:
✅ Конструктор
✅ Геттеры (но без get в названии)
✅ equals(), hashCode(), toString()
🔹 Пример использования
public record User(String name, int age) {}
equals/hashCode/toString, но занимает всего одну строку! record всегда final record запрещено
🔥 5 паттернов проектирования, которые должен знать каждый Java-разработчик
В мире 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;
}
}
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("Неизвестный тип продукта");
}
}
@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();
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); }
}
}
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);
}
}
1️⃣ Чем 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 в своих проектах? Делитесь опытом! 🚀
🚀Как правильно использовать Optional в Java Optional<T> в Java — это мощный инструмент для работы с возможными null значениями, но часто его используют неправильно. Давайте разберём основные ошибки и лучшие практики.
❌ Плохие примеры:
1️⃣ Использование Optional как поля в классе
class User {
Optional<String> name; // ❌ Плохая практика
}
String, а если нужно, то оборачивать значение в Optional при возврате. 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? Пишите в комментариях! 🚀
🚀Разбираем принцип работы ConcurrentHashMap
Сегодня разберёмся, почему 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
}
}
🚀 Совет по Java API 🚀
При использовании Integer.valueOf(int) помните, что значения в диапазоне от -128 до 127 кэшируются для повышения производительности. За пределами этого диапазона создаются новые объекты.
Размер кэша можно контролировать с помощью опции -XX:AutoBoxCacheMax=<размер>. 🔥
📲 Мы в MAX
👉@BookJava
👩💻 Открытый урок «Spring Boot Actuator: основы мониторинга и управления приложением»
🗓 30 марта в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework» от Otus.
Узнайте, как эффективно реализовать интернационализацию и локализацию в Spring-приложениях.
На вебинаре разберем:
Знакомимся с базовыми возможностями Spring Boot Actuator — важным инструментом для контроля приложений.
О чём поговорим:
✔️ Зачем нужен Spring Boot Actuator.
✔️ Какие задачи решает при работе с приложениями.
✔️ Базовая настройка Actuator.
✔️ Просмотр метрик и их значение.
Кому будет интересно:
Начинающим Java-разработчикам и инженерам, впервые сталкивающимся с задачами мониторинга приложений.
🔗 Ссылка на регистрацию: https://vk.cc/cVR0CO
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Совет по Java 💡
Чтобы сделать большие и сложные цепочки компараторов более читаемыми, мне нравится присваивать компараторы переменным, имена которых начинаются с "by". Таким образом, вызов sorted() становится меньше и читается почти как естественный язык. Кроме того, вы можете использовать статический импорт.
📲 Мы в MAX
👉@BookJava
🔌 Проектирование API: REST, GraphQL или gRPC?
🧱 1. REST (Классика и Стандарт)
REST (Representational State Transfer) - это де-факто стандарт интернета. Большинство публичных API (GitHub, Stripe, Telegram) построены на нем.
Суть: В центре всего находится Ресурс (Существительное). А действия над ним выполняются через стандартные HTTP-методы (Глаголы).
• GET /users/123 - Дай мне пользователя 123.
• POST /users - Создай пользователя.
• DELETE /users/123 - Удали пользователя.
✅ Плюсы:
• Простота: Понятен всем, легко тестировать через Postman или браузер.
• Кэширование: Идеально работает с CDN (о которых мы говорили раньше), так как использует стандартные механизмы HTTP.
❌ Минусы:
• Over-fetching (Избыточность): Мобильному приложению нужно только имя пользователя, но метод GET /users/1 возвращает огромный JSON на 50 полей (с адресами, датами и т.д.). Вы тратите трафик впустую.
• Under-fetching (Недостаточность) и проблема N+1: Чтобы показать профиль пользователя и его 10 последних постов, фронтенду придется сделать 1 запрос к /users/1 и еще 10 запросов к /posts?userId=1. Это медленно.
🕸️ 2. GraphQL (Мечта Фронтендера)
Разработан в Facebook для решения проблем REST при слабом мобильном интернете.
Суть: У вас есть всего один Endpoint (обычно POST /graphql). Клиент сам пишет запрос-схему, где указывает, какие конкретно поля ему нужны.
Запрос клиента:
query {
user(id: "123") {
name
posts(last: 10) {
title
}
}
}
/users-with-posts-and-comments.POST /graphql, вы не можете просто закэшировать это на уровне CDN (Cloudflare)."name": "Alex", он передает просто байты по заранее оговоренной жесткой схеме (.proto файл)..proto файле, и из него автоматически генерируется код и для Java-бэкенда, и для Python-клиента. Никаких ошибок "ожидал строку, пришло число".grpc-web), поэтому для публичного фронтенда его почти не используют.
🕸️ Service Mesh: Инфраструктура, невидимая для кода
❌ Проблема: "Толстые" микросервисы
Если вы используете Spring Cloud (Netflix OSS), ваша бизнес-логика перемешана с сетевой логикой.
Вам нужно добавлять в код Java аннотации для ретраев (повторных запросов), настраивать Circuit Breaker (Предохранитель), писать логику для распределенной трассировки.
А теперь представьте, что в компанию пришла команда, которая пишет на Go или Node.js. Им придется искать аналоги всех этих библиотек для своих языков! Разве сеть это проблема программиста? Нет, это проблема инфраструктуры.
🦸♂️ Решение: Service Mesh и паттерн Sidecar
Service Mesh (Сервисная сетка) - это выделенный инфраструктурный слой для безопасного, быстрого и надежного общения микросервисов друг с другом. Самый популярный инструмент на рынке - Istio.
Вся магия строится на паттерне Sidecar (Коляска мотоцикла).
Рядом с вашим контейнером Java в том же поде (Pod) Kubernetes незаметно запускается второй маленький контейнер - Proxy-сервер (обычно это Envoy).
Теперь ваше Java-приложение вообще ничего не знает о внешнем мире.
1. Оно хочет отправить запрос в PaymentService? Оно просто шлет HTTP-запрос на localhost.
2. Sidecar-прокси перехватывает этот запрос.
3. Sidecar сам находит нужный сервис, сам шифрует трафик, сам делает ретраи, если сеть моргнула, и отправляет запрос другому Sidecar-у на стороне PaymentService.
🎛️ Как устроен Istio: Data Plane и Control Plane
• Data Plane (Плоскость данных): Это армия тех самых Sidecar-прокси (Envoy), которые стоят рядом с каждым сервисом и перекидывают байты.
• Control Plane (Плоскость управления): Это мозг (Istiod). Он раздает команды всем прокси-серверам: "Так, с сегодняшнего дня все запросы шифруем", "А теперь 5% трафика направь на новую версию сервиса".
✨ Суперспособности Service Mesh
Зачем терпеть усложнение архитектуры? Ради этих фич:
1. Управление трафиком (Traffic Routing)
Вам больше не нужно деплоить новую версию на всех сразу и молиться, чтобы она не упала.
Вы можете сказать Istio: "Пусти 99% пользователей на версию v1, и только 1% пользователей с iPhone - на версию v2 (Канареечный релиз)". Если v2 работает стабильно, плавно увеличиваем процент.
2. Нулевое доверие (Zero-Trust Security & mTLS)
Если хакер проникнет во внутреннюю сеть дата-центра, он сможет "слушать" трафик между вашими сервисами (там могут лететь пароли и токены в открытом виде).
Istio из коробки включает mTLS (Mutual TLS). Трафик между ВСЕМИ микросервисами автоматически шифруется. При этом разработчикам не нужно возиться с сертификатами в Java-коде.
3. Наблюдаемость (Observability) без кода
Помните Jaeger, Zipkin и Prometheus из прошлого сезона? Чтобы они работали, мы добавляли библиотеки в pom.xml.
С Service Mesh это не нужно! Так как все запросы проходят через Sidecar-прокси, он сам собирает метрики (сколько времени занял запрос, какие были ошибки) и сам рисует красивые графы зависимостей в Grafana и Jaeger.
4. Устойчивость к сбоям (Resilience)
Если PaymentService "лежит", Sidecar может автоматически сделать 3 повторные попытки (Retry) с интервалом в секунду. Если сервис всё равно не отвечает, Sidecar включит Circuit Breaker (разорвет цепь) и будет сразу возвращать ошибку, чтобы не перегружать зависший сервис.
⚔️ Service Mesh vs API Gateway
Часто спрашивают: "Зачем мне Istio, если у меня уже есть Spring Cloud Gateway?"
• API Gateway: Управляет трафиком Север-Юг (Снаружи вовнутрь). Он стоит на границе интернета и вашей системы, принимает запросы от пользователей, проверяет JWT-токены и пускает внутрь.
• Service Mesh: Управляет трафиком Восток-Запад (Внутри системы). Он следит за тем, как микросервисы общаются между собой за закрытыми дверями.
🔥 Итог
Service Mesh (Istio) - это инструмент для крупных и сложных систем.
Если у вас 5 микросервисов - это оверкилл, используйте Spring Cloud.
Если у вас 100 микросервисов на разных языках программирования, строгие требования к безопасности (банки) и частые релизы без Service Mesh вы сойдете с ума.
#SystemDesign #ServiceMesh #Istio #Microservices #DevOps
📲 Мы в MAX
👉@BookJava
🔎 Elasticsearch: Как найти иголку в стоге сена за 10 мс
Представьте каталог на 10 миллионов товаров. Пользователь вводит в поиск: "айфон 15 про макс".
🐌 1. Почему SQL здесь бессилен?
В реляционной базе (PostgreSQL/MySQL) вы бы написали:SELECT * FROM products WHERE name LIKE '%айфон 15%'
В чем проблема?
1. Full Table Scan: База данных не может использовать обычный B-Tree индекс для поиска по части слова (с LIKE '%...'). Ей придется прочитать все 10 миллионов строк на диске, чтобы найти совпадения. Это убьет процессор.
2. Нулевая толерантность к ошибкам: Если пользователь опечатался и написал "айфно", SQL вернет 0 результатов. Бизнес потерял клиента.
3. Нет релевантности: SQL не понимает, какой товар подходит "лучше". Он просто отдает всё, что нашел, по дате добавления.
🧠 2. Инвертированный индекс (Inverted Index)
Чтобы искать по тексту мгновенно, умные люди придумали структуру данных, которая работает как алфавитный указатель в конце толстой книги.
Вместо того чтобы искать слово на страницах, мы заранее составляем список всех слов и записываем, на каких страницах они встречаются.
Пример:
У нас есть три товара (Документа):
• Doc 1: "Красный телефон Apple"
• Doc 2: "Синий чехол для телефона"
• Doc 3: "Красный чехол"
Инвертированный индекс будет выглядеть так:
• красный -> [Doc 1, Doc 3]
• телефон -> [Doc 1, Doc 2]
• apple -> [Doc 1]
• синий -> [Doc 2]
• чехол -> [Doc 2, Doc 3]
Теперь, если мы ищем "красный телефон", система просто берет списки для этих двух слов: [1, 3] и [1, 2]. Пересечение этих списков - Doc 1. Мы нашли результат за O(1)! Никакого сканирования миллионов строк.
🚀 3. Встречайте Elasticsearch (ES)
Elasticsearch - это не просто база данных, это полноценный поисковый движок (написанный на Java поверх библиотеки Apache Lucene).
Он хранит данные не в таблицах, а в виде JSON-документов, и автоматически строит инвертированный индекс для каждого текстового поля.
🪄 Магия Elasticsearch:
1. Анализаторы (Стемминг и Лемматизация): Перед тем как положить текст в индекс, ES его обрабатывает. Он приводит слова к базовой форме, убирает окончания и предлоги.
• Слова "айфон", "айфону", "айфоном" попадут в индекс как один токен "айфон".
2. Поиск с опечатками (Fuzzy Search): ES использует Расстояние Левенштейна (сколько букв нужно изменить, чтобы получить правильное слово).
• Запрос "йафон" автоматически найдет "айфон", потому что разница всего в одну перестановку.
3. Релевантность (Scoring - BM25): ES каждому результату присваивает "Оценку". Чем реже слово встречается во всей базе и чем чаще в конкретном документе, тем выше этот документ будет в выдаче.
🏗️ 4. Как это выглядит в Архитектуре?
Важное правило: Elasticsearch не заменяет вашу основную базу данных.
ES - это поисковик. Он может потерять данные при сбоях (он оптимизирован на скорость чтения, а не на надежность хранения ACID).
Правильный паттерн (CQRS-лайт):
1. "Правда" живет в PostgreSQL.
2. Когда товар добавляется или меняется в Postgres, вы отправляете событие в брокер сообщений (Kafka) или используете CDC (Change Data Capture - например, Debezium), чтобы прочитать логи БД.
3. Специальный воркер берет эти изменения из Kafka и синхронизирует их с Elasticsearch.
4. Фронтенд: за созданием/покупкой товара ходит в Postgres, а за поиском — в Elasticsearch.
🔥 Итог
• SQL LIKE - для админок и маленьких таблиц.
• Инвертированный индекс - ключ к мгновенному поиску.
• Elasticsearch - стандарт индустрии для полнотекстового умного поиска, логов (помните ELK?) и аналитики.
#SystemDesign #Elasticsearch #Search #Architecture #HighLoad
📲 Мы в MAX
👉@BookJava
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
🚀 5 полезных библиотек для Java-разработчика
🔹 Lombok – убирает бойлерплейт-код. Автоматически генерирует геттеры, сеттеры, конструкторы, toString(), equals(), hashCode(). Больше не нужно писать однотипный код вручную!
🔹 Guava – коллекции, кэширование, строки, примитивные типы, функциональные утилиты и многое другое. Разработана Google, широко используется в индустрии.
🔹 Apache Commons – набор утилит для работы со строками, коллекциями, потоками, датами. Позволяет сократить код и улучшить его читаемость.
🔹 Jackson – одна из лучших библиотек для работы с JSON. Позволяет сериализовать и десериализовать Java-объекты быстро и без лишнего кода.
🔹 Junit + Mockito – тестирование в Java. JUnit – основной инструмент для написания юнит-тестов, а Mockito помогает мокировать зависимости и тестировать сложные сценарии.
📲 Мы в MAX
👉@BookJava
🚀 Разбираемся с var в Java: Когда использовать, а когда нет?
Сегодня разберёмся с var в Java. Этот локальный тип вывода переменной появился в Java 10 и сразу вызвал много споров. Давайте посмотрим, когда его стоит использовать, а когда лучше отказаться.
✅ Когда var полезен?
1️⃣ Сокращение шаблонного кода
var list = new ArrayList<String>(); // читается проще
var map = new HashMap<String, List<Integer>>();
var thread = new Thread(() -> System.out.println("Hello"));
for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
var ухудшает код?
var data = fetchData(); // Что вернет метод? Интуитивно непонятно!
var something = doSomethingComplicated(); // А что это такое?
var, мы теряем контракт с пользователем API.var, когда тип очевиден и код становится чище. Не злоупотребляйте им, чтобы не терять читаемость!
Совет Spring Framework💡
Вы можете автосопрягать несколько бинов, реализующих определенный интерфейс, в список, содержащий все реализации. Определите список с общим типом, который вы хотите использовать. Вы можете использовать инъекцию конструктора, как показано на картинке, или инъекцию поля.
📲 Мы в MAX
👉@BookJava
🚀 Stream API в Java: 5 мощных трюков, которые ты мог не знать
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]}
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]
skip(n))
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]
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
anyMatch())
List<Integer> nums = List.of(10, 50, 200, 30);
boolean hasLargeNumber = nums.stream().anyMatch(n -> n > 100);
System.out.println(hasLargeNumber); // true
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
🔥 Разбираем 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() позволяет асинхронно обработать результат.
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() объединяет результаты двух асинхронных задач. 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(), и программа не упадёт.
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.
🔴 Завтра тестовое собеседование с Java-разработчиком
1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Виктору
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
В чем разница между Checked и Unchecked исключениями во время выполнения?
Да, в Java есть существенные различия между checked (проверяемыми) и unchecked (непроверяемыми) исключениями во время выполнения.
1. Проверка на этапе компиляции
- Checked исключения: Проверяются на этапе компиляции. Компилятор требует, чтобы вы либо обработали исключение (с помощью try-catch), либо объявили его в сигнатуре метода (с помощью throws). Если этого не сделать, код не скомпилируется.
- Unchecked исключения: Не проверяются на этапе компиляции. Компилятор не требует их обработки или объявления. Обычно они возникают из-за логических ошибок в коде (например, NullPointerException, ArrayIndexOutOfBoundsException).
2. Поведение во время выполнения
- Checked исключения: Эти исключения обычно связаны с внешними факторами (например, проблемы с файловым вводом-выводом, сетевыми соединениями) и могут возникать в ходе нормального выполнения программы. Если такое исключение выбрасывается и не обрабатывается, оно будет передаваться вверх по стеку вызовов, пока не будет перехвачено или программа не завершится.
- Unchecked исключения: Эти исключения часто вызваны ошибками в коде (например, деление на ноль, обращение к null). Если такое исключение выбрасывается и не перехватывается, оно также будет передаваться вверх по стеку вызовов, но, поскольку их не требуется объявлять или обрабатывать, это может привести к неожиданному завершению программы.
3. Наследование
- Checked исключения: Все исключения, которые наследуют Exception (но не RuntimeException), являются проверяемыми.
- Unchecked исключения: Все исключения, которые наследуют RuntimeException или Error, являются непроверяемыми.
4. Примеры
- Checked исключения: IOException, SQLException, ClassNotFoundException.
- Unchecked исключения: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException.
5. Обработка во время выполнения
- Checked исключения: Поскольку они проверяются на этапе компиляции, вы обязаны явно их обрабатывать. Это делает код более устойчивым, но может увеличить его объем.
- Unchecked исключения: Поскольку они не проверяются на этапе компиляции, их сложнее отлаживать и обрабатывать, так как они могут быть неочевидными в коде.
6. Производительность
- Нет значительной разницы в производительности между checked и unchecked исключениями во время выполнения. Стоимость выбрасывания и перехвата исключений одинакова для обоих типов.
Итог
- Checked исключения: Контролируются компилятором, должны быть обработаны или объявлены, обычно используются для recoverable (восстанавливаемых) ситуаций.
- Unchecked исключения: Не контролируются компилятором, часто возникают из-за ошибок в коде и могут привести к аварийному завершению программы, если не обработаны.
Оба типа исключений ведут себя схожим образом во время выполнения, но ключевое различие заключается в том, как они контролируются и обрабатываются на этапе разработки.
📲 Мы в MAX
👉@BookJava
Совет по Java 💡☕️
Чтобы получить все дни месяца, вы можете начать с объекта YearMonth, получить его первый день, а затем использовать функцию datesUntil(), которая возвращает Stream всех дней до указанной даты.
📲 Мы в MAX
👉@BookJava
🖥️ Java: передача по значению или по ссылке? 🤔
В Java передача данных происходит ТОЛЬКО по значению (pass-by-value). Однако работа с объектами может ввести в заблуждение и создать впечатление, что передача идет по ссылке.
🔹 Как работает передача в Java?
✅ Примитивные типы (int, double, char): передается копия значения. Изменения внутри метода не влияют на оригинальную переменную.
✅ Объекты (экземпляры классов): передается копия ссылки на объект, а не сам объект. Внутри метода можно изменить состояние объекта, но нельзя изменить саму ссылку на него.
📌 Примеры
🔹 Передача примитивов (значение не изменяется)
public class Test {
public static void modifyPrimitive(int num) {
num = 10; // Это изменение локальное
}
public static void main(String[] args) {
int x = 5;
modifyPrimitive(x);
System.out.println(x); // Выведет: 5 (не изменилось)
}
}
class Person {
String name;
}
public class Test {
public static void modifyObject(Person p) {
p.name = "Alice"; // Изменяет состояние объекта
}
public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
modifyObject(person);
System.out.println(person.name); // Выведет: Alice
}
}
class Person {
String name;
}
public class Test {
public static void reassignReference(Person p) {
p = new Person(); // Переназначение ссылки (локально)
p.name = "Charlie";
}
public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
reassignReference(person);
System.out.println(person.name); // Выведет: Bob (не изменилось)
}
}
Scala создан на базе Java, но при этом остаётся более лаконичным и выразительным языком. При этом они отлично сочетаются: вы можете использовать Java-код внутри Scala. На Scala разрабатывают микросервисы, системы аналитики, решения для машинного обучения и обработки данных, а также высоконагруженные сервисы.
Приглашаем на серию открытых уроков перед стартом курса «Scala-разработчик»:
📆1 апреля в 20:00
Разберём функциональную валидацию данных с помощью Cats Validated. Поговорим, почему Either неудобен для таких задач, научимся собирать все ошибки сразу и реализуем валидацию формы регистрации. Вы поймёте, когда использовать Validated, а когда Either, и сможете применять это в реальном коде.
📆14 апреля в 20:00
Изучим ключевые возможности Scala через case classes и pattern matching. На практике разберём, как создавать безопасные модели данных, работать с событиями и писать чистый, понятный код, который используется в production.
📆20 апреля в 20:00
Погрузимся в тему эффектов в Scala. Разберём, что такое эффекты и как они помогают писать предсказуемый и масштабируемый код. Рассмотрим Option, Either, Future, а также Cats Effect и ZIO, и покажем, как применять их в реальных задачах.
💥Присоединяйтесь, чтобы прокачать навыки Scala и функционального программирования на практике. Подробности об уроках и регистрация: https://vk.cc/cVMvN3
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Вы знаете названия шаблонов проектирования, но сможете ли выбрать архитектуру, которая выдержит реальную нагрузку? CQRS, Event Sourcing, Saga Pattern звучат убедительно. Но каждый из этих подходов решает конкретные задачи — и добавляет сложности. Ошибка в выборе архитектуры часто обходится дороже, чем ошибка в коде.
На открытом уроке «Основные шаблоны проектирования в системном дизайне»:
- разберём ключевые архитектурные паттерны на практических примерах (высоконагруженные сервисы, распределённые транзакции, масштабируемые системы).
- обсудим, в каких сценариях подход оправдан, а где он только усложняет систему.
- поговорим о компромиссах (сложность, стоимость внедрения, производительность).
Ведущий Роман Грицуляк — разработчик, консультант по проектированию ИТ-систем.
Открытый урок проходит в преддверии старта курса «Проектирование систем».
Регистрируйтесь сейчас - напомним перед вебинаром: регистрация
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🌍 CDN: Как обмануть скорость света и расстояния
CDN (Content Delivery Network / Сеть доставки контента) - это географически распределенная сеть серверов, задача которых - отдавать контент пользователю из максимально близкой к нему точки.
🏢 1. Origin и Edge: Разделение ролей
В архитектуре с CDN появляются два новых понятия:
• Origin Server (Главный сервер): Это ваш настоящий сервер, где крутится Spring Boot, лежит база данных и хранятся оригиналы всех файлов (например, в Amazon S3).
• Edge Servers (Граничные серверы / Точки присутствия - PoP): Это тысячи серверов CDN-провайдера (например, Cloudflare или Akamai), раскиданные по всему земному шару: в Сиднее, Токио, Нью-Йорке, Лондоне, Москве.
⚙️ 2. Как это работает (Cache Hit & Miss)
Представьте, что австралийский пользователь впервые запрашивает логотип вашего сайта logo.png.
1. Cache Miss (Промах кэша): Запрос летит на ближайший к нему Edge-сервер в Сиднее. Сервер проверяет свою память и видит: "У меня нет этого файла".
2. Поход на Origin: Edge-сервер сам идет на ваш главный сервер в Германию, скачивает logo.png, сохраняет копию у себя на диске (кэширует) и отдает пользователю. Это было долго (те самые 300 мс).
3. Cache Hit (Попадание в кэш): Через секунду заходит второй пользователь из Сиднея и просит тот же logo.png. Edge-сервер моментально отдает ему файл из своей памяти за 5 миллисекунд. Запрос до Германии даже не доходит!
📦 3. Что кладем в CDN, а что нет?
CDN идеально подходит для Статического контента:
• Картинки, видео, аудио.
• Скомпилированные файлы JavaScript и CSS.
• Шрифты.
CDN категорически НЕ подходит для Динамического контента:
• Баланс банковского счета.
• Корзина товаров.
• Приватные данные пользователя.
• (Запросы к API /api/v1/users/me должны идти напрямую на ваш сервер, минуя кэш CDN).
🛡️ 4. Защита от DDoS
Современные CDN (тот же Cloudflare) - это не просто кэш. Это гигантский щит.
Если хакеры решат "положить" ваш сайт и отправят миллион запросов в секунду, этот удар примут на себя серверы CDN. Их пропускная способность измеряется терабитами. Они отфильтруют "мусорный" трафик, и ваш маленький Origin-сервер в Германии даже не заметит атаки.
🔥 Итог
• Ускорение: Пользователи получают тяжелый контент мгновенно, потому что скачивают его из своего же города.
• Экономия: Ваш главный сервер больше не тратит процессорное время и трафик на отдачу терабайтов картинок. Вы платите за сервера меньше.
• Безопасность: CDN скрывает реальный IP-адрес вашего сервера и защищает от DDoS-атак.
#SystemDesign #CDN #Cloudflare #Architecture #HighLoad
📲 Мы в MAX
👉@BookJava
🗄️ System Design: Как не "положить" Базу Данных?
В большинстве веб-приложений (например, Instagram или Twitter) соотношение чтения к записи составляет примерно 10 к 1. То есть люди в 10 раз чаще смотрят чужие посты, чем пишут свои.
Эту особенность мы и будем использовать.
👯♂️ 1. Репликация (Master-Slave / Leader-Follower)
Идея проста: давайте скопируем базу данных на несколько серверов и разделим обязанности.
🔴Master (Лидер): Это единственная база данных, в которую разрешено ПИСАТЬ (INSERT, UPDATE, DELETE).
🔴Slave (Ведомые/Реплики): Это точные копии Мастера. Из них можно ТОЛЬКО ЧИТАТЬ (SELECT).
Как это работает:
1. Пользователь публикует фото. Запрос идет на Master-базу.
2. Master сохраняет фото и мгновенно отправляет новые данные всем своим Slave-копиям (реплицирует).
3. 1000 других пользователей открывают ленту. Их запросы на чтение распределяются между тремя Slave-базами.
Итог: Нагрузка на чтение размазана, Мастер спокойно занимается только записью.
🪓 2. Шардирование (Sharding / Горизонтальное партиционирование)
Репликация спасает, когда много читают. Но что делать, если пользователи слишком много пишут (например, это система сбора логов или мессенджер)? Мастер перестает справляться.
Или что делать, если данных стало 10 Терабайт, и они тупо не влезают на один диск?
Приходит время рубить данные на части - Шардировать.
Мы берем нашу огромную таблицу Users и разбиваем её на несколько независимых баз данных (Шардов).
🔴Шард 1: Хранит пользователей с ID от 1 до 1,000,000.
🔴Шард 2: Хранит пользователей с ID от 1,000,001 до 2,000,000.
Каждый Шард - это отдельный сервер со своим процессором и диском.
Сложность: Теперь вашему приложению (или специальному роутеру) нужно понимать, в какую именно базу отправлять SQL-запрос. А сделать JOIN между таблицами, лежащими на разных серверах, становится практически невозможно.
📐 3. Теорема CAP (Закон распределенных систем)
Как только ваша база данных перестает жить на одном сервере и разъезжается на несколько (реплики или шарды), вступает в силу суровый закон физики - Теорема CAP.
Она гласит, что в распределенной системе вы можете выбрать только ДВА из ТРЕХ свойств:
1. C (Consistency / Консистентность): Все клиенты видят одни и те же данные в один и тот же момент времени. (Если я обновил аватарку на Мастере, следующий же запрос к любому Слейву должен вернуть новую аватарку).
2. A (Availability / Доступность): Система всегда отвечает на запрос, даже если часть серверов сгорела. Никаких ошибок 500.
3. P (Partition Tolerance / Устойчивость к разделению): Система продолжает работать, даже если между серверами БД пропала сеть (они перестали видеть друг друга).
Суровая реальность: В интернете сеть пропадает всегда. Поэтому свойство P мы обязаны брать по умолчанию. Остается выбор между CP и AP.
🔴Системы CP (Консистентные): Банковские приложения. Если сеть между Мастером и Репликой упала, база откажется отдавать вам баланс, потому что боится отдать устаревшие данные. Лучше выдать ошибку, чем соврать.
🔴Системы AP (Доступные): Соцсети (Instagram, YouTube). Если вы поставили лайк, а сеть внутри дата-центра моргнула, ваш друг может еще пару минут не видеть этот лайк (данные не консистентны). Но сайт при этом не "лежит", лента листается. Это называется Eventual Consistency (Консистентность в конечном счете).
🔥 Итог
🔴Используйте Репликацию, чтобы масштабировать чтение (Read-heavy).
🔴Используйте Шардирование, чтобы масштабировать запись и объем данных (Write-heavy).
🔴Помните про CAP-теорему: для соцсетей выбираем Доступность (AP), для финансов - Консистентность (CP).
📲 Мы в MAX
👉@BookJava