Java библиотека – Telegram
Java библиотека
31.5K subscribers
2.37K photos
90 videos
10 files
2.18K links
Книги, статьи, мемы и многое другое для Java программиста!

По сотрудничеству и рекламе: @NadikaKir

Канал в перечне РКН: https://vk.cc/cJrT4A

Мы на бирже: https://telega.in/c/javalib/

Сообщество VK https://vk.com/javatutorial
Download Telegram
Принципы SOLID

Как разработчики, мы стремимся к тому, чтобы наш код был поддерживаемым, масштабируемым и готовым к изменениям. Один из способов достичь этого — следовать принципам SOLID. Эти пять принципов проектирования помогают создавать системы, которые легко понимать и поддерживать, что ведет к более чистому и надежному коду.

Рассмотрим каждый принцип:

1️⃣ Принцип единственной ответственности (S)
Каждый класс должен иметь только одну причину для изменения, то есть он должен отвечать за одну задачу или ответственность. Это достигается за счет того, что классы фокусируются на выполнении конкретных задач. Соблюдение этого принципа делает код более модульным и простым в поддержке.

2️⃣ Принцип открытости/закрытости (O)
Классы должны быть открыты для расширения, но закрыты для изменения. Это значит, что поведение класса можно расширять, не изменяя его существующий код. В Java это часто реализуется через использование интерфейсов или абстрактных классов.

3️⃣ Принцип подстановки Барбары Лисков (L)
Объекты суперкласса должны заменяться объектами подкласса без нарушения корректности программы. В Java это особенно важно при работе с наследованием, чтобы подклассы правильно расширяли базовые классы, не изменяя их поведение.

4️⃣ Принцип разделения интерфейса (I)
Клиенты не должны зависеть от интерфейсов, которые они не используют. В Java это достигается путем разделения крупных интерфейсов на более узкоспециализированные, чтобы классы реализовывали только те методы, которые им действительно нужны.

5️⃣ Принцип инверсии зависимостей (D)
Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций. В Java это часто реализуется через внедрение зависимостей (Dependency Injection), которое позволяет передавать зависимости извне, что способствует слабой связности и гибкости системы.

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥85
🔥16 октября в 20:00 мск — открытый вебинар в OTUS!

О чём?

Хотите объединять данные из разных источников в PostgreSQL без сложных ETL-процессов? Foreign-Data Wrappers (FDW) позволяют превратить PostgreSQL в мощный центр управления данными из внешних баз, облачных хранилищ и систем больших данных.

Что разберём:


- Foreign-Data Wrappers: как они работают в PostgreSQL.
- Интеграция: подключение к внешним базам (MySQL, MongoDB и др.) и управление данными как локальными таблицами.
- Примеры: объединение данных из разных источников без ETL.
- Облачные решения: использование FDW с облачными хранилищами и Big Data.
- Оптимизация: лучшие практики настройки FDW для высокой производительности.

🎓 После вебинара вы:

- Научитесь подключать PostgreSQL к внешним источникам через FDW.
- Освоите настройку и интеграцию данных для гибридных систем..

🔧 Присоединяйтесь, чтобы раскрыть потенциал PostgreSQL и упростить интеграцию данных в ваших проектах!

👉 Зарегистрироваться https://vk.cc/cQnyg6

Бесплатное занятие приурочено к старту курса Highload Architect, обучение на котором позволит освоить решения, которые выдерживают большое количество запросов в секунду и правильно оптимизировать работоспособность серверов

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👍32🔥2
CompletableFuture

CompletableFuture — это класс в Java, введенный в Java 8, который представляет собой асинхронную задачу, которая будет выполнена в будущем и возвращает результат. CompletableFuture предоставляет множество методов для работы с асинхронными задачами, комбинирования их и управления их выполнением.

Основные возможности CompletableFuture включают:

— Вы можете запустить задачу асинхронно и продолжить выполнение кода без блокировки.
— CompletableFuture позволяет комбинировать результаты нескольких задач, выполняя определенные действия при завершении каждой задачи.
— Вы можете указать обработчики ошибок для обработки исключений, возникающих во время выполнения задачи.
— Вы можете блокировать выполнение кода и ждать завершения задачи.


Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥64
Поговорим про деньги в IT?

Приглашаем опытных IT-специалистов пройти небольшой опрос про зарплаты и бенефиты в технологических компаниях. Это займёт не более 7 минут — а ваше мнение поможет одному крупному российскому работодателю делать актуальные оферы.

Пройти опрос можно здесь
👍4🔥32
👩‍💻 Spring Boot + Docker Compose: пошаговая интеграция

В проде редко гоняют приложения напрямую — почти всегда через Docker. А с появлением spring-boot-docker-compose интеграция стала проще: можно поднимать всю инфраструктуру (Postgres, Redis, Kafka и т.д.) одной командой вместе с приложением.

1️⃣ Подготовка зависимостей

В Spring Boot 3.1 добавили официальный стартер:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<scope>runtime</scope>
</dependency>

ИЛИ

dependencies {
runtimeOnly("org.springframework.boot:spring-boot-docker-compose")
}


2️⃣ docker-compose.yml

Определим инфраструктуру (например, Postgres + pgAdmin):
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: app-postgres
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data

pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: admin@app.local
PGADMIN_DEFAULT_PASSWORD: secret
ports:
- "8081:80"
depends_on:
- postgres

volumes:
postgres_data:


3️⃣ Автоматическая интеграция

Spring Boot сам подтянет конфигурацию из docker-compose.yml. Просто укажите профиль:
./mvnw spring-boot:run -Dspring.profiles.active=compose


или
./gradlew bootRun --args='--spring.profiles.active=compose'


При старте Boot поднимет контейнеры и подставит spring.datasource.url, username, password.

4️⃣ Кастомизация application-compose.yml

Если нужны дополнительные параметры — кладём их в src/main/resources/application-compose.yml:
spring:
datasource:
hikari:
maximum-pool-size: 5


5️⃣ Полезные приёмы

— Фиксируйте версии образов, а не latest (для воспроизводимости).

— Healthcheck в docker-compose.yml помогает Boot ждать готовности контейнера.

— Можно запускать docker compose up -d руками, если не хотите, чтобы Boot сам управлял контейнерами.

— Для CI/CD обычно используют отдельные docker-compose.override.yml или Helm чарты, но для дев-окружения spring-boot-docker-compose очень экономит время.

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥216👍5
Худи RYBE для Java — это функциональная вещь

Мы добавили несколько фичей, чтобы тебе было классно и комфортно:

⚫️Карман на металлических кнопках
⚫️Салфетка для очков или экрана в кармане
⚫️Люверсы для пропуска
⚫️Удобный шнурок
⚫️Надпись на капюшоне и одна особенная внутри него
⚫️Карман внутри для наушников, чтобы они не болтались и не терялись 
 
Заказать свою толстовку можно на сайте: http://rybe.store/
Наш tg

Реклама ИП Кольцова Римма Алексеевна, ИНН 760212761004, erid: 2Vtzqux1uxZ
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9👍4
Внутреннее устройства HashMap

HashMap — один из базовых и в то же время самых хитро устроенных контейнеров в JDK. На поверхности простая структура «ключ–значение», но под капотом она сочетает массивы, списки и даже деревья, чтобы оставаться быстрой в разных сценариях нагрузки.

📦 Базовая структура

HashMap хранит данные в массиве бакетов (Node<K,V>[] table). Каждый бакет — это «корзина» для элементов, чей hashCode после хеширования и применения & (n-1) (где n — длина массива) указывает на конкретный индекс.

🔑 Хэш и распределение

1. Вызов hashCode() у ключа.
2. Дополнительное хеширование (spread), чтобы снизить коллизии из-за плохой реализации hashCode.
3. Индекс бакета = hash & (table.length - 1).

🌊 Коллизии

Если несколько ключей попали в один бакет:

— до Java 8 это всегда был связанный список (linked list),

— начиная с Java 8: при росте числа элементов в бакете больше 8 и достаточном размере таблицы он превращается в сбалансированное красно-чёрное дерево. Это резко ускоряет поиск в «плохих» случаях (с O(n) до O(log n)).

⚡️ Ресайзинг

Когда количество элементов превышает capacity * loadFactor (по умолчанию 0.75), создаётся новый массив в 2 раза больше, все элементы перехешируются и раскладываются по новым бакетам. Это дорогостоящая операция, но благодаря амортизации остаётся приемлемой.

📊 Производительность


— Поиск/вставка/удаление в среднем: O(1).

— В худшем случае (плохой hashCode + коллизии): O(log n) благодаря деревьям.

⚖️ Важные нюансы


— Ключи неупорядочены. Для упорядоченности есть LinkedHashMap.

— HashMap не потокобезопасен. Для многопоточной среды нужен ConcurrentHashMap или синхронизация.

— Хорошо реализованный hashCode и equals критичны, иначе получите «забитые» бакеты и деградацию.

🧮 loadFactor и capacity


— Capacity — размер массива бакетов. По умолчанию 16.

— LoadFactor — коэффициент заполнения. По умолчанию 0.75.

Почему именно 0.75? Это компромисс: выше → меньше памяти, но больше коллизий; ниже → быстрее доступ, но больше памяти уходит впустую. Capacity всегда степень двойки, чтобы можно было вычислять индекс через hash & (n-1) вместо затратного %.

🔄 Итераторы и fail-fast

Если во время обхода карта меняется (кроме iterator.remove()), бросается ConcurrentModificationException. Под капотом это работает через счётчик модификаций (modCount), который проверяется в каждом next().

🌳 Деревья в деталях

Коллизии превращаются в красно-чёрное дерево, если размер списка в бакете > 8 и общее количество бакетов ≥ 64. Обратно в список (untreeify) при падении количества элементов < 6. Это сделано, чтобы не тратить память и CPU на лишнюю балансировку при малых размерах.

🔗 Документация: OpenJDK — HashMap source

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍165🔥5
🔥 Современная оркестрация Kotlin-приложениями

Приглашаем на открытый урок.

🗓 22 октября в 19:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Kotlin Backend Developer. Professional».

Уже прошла эпоха монолита, когда целые компании занимались разработкой одного необъятного приложения. Сейчас любая информационная система насыщена различными сервисами, а микросервисами уже никого не удивишь.
Обязательным атрибутом собеседований стал вопрос про Saga, хореографию и оркестрацию.
И именно эту тему мы разберем на вебинаре в применении к Kotlin-разработке.

Что будет на вебинаре:
- Обсудим как традиционные оркестраторы типа Airflow или Camunda, так новых игроков.
- На практической части вебинара мы разработаем простое приложение, управляемое оркестратором.

🔗 Ссылка на регистрацию: https://vk.cc/cQpCBu

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥2
Gradle

Это инструмент автоматизации сборки, который в основном используется в Android-разработке. Популярная альтернатива Ant и Maven.

Gradle позволяет определять и управлять зависимостями проекта, запускать модульные тесты и упаковывать приложение для развертывания. Gradle также имеет систему плагинов, которая позволяет добавлять функциональные возможности и настраивать процесс сборки.


Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4🔥31😁1
👩‍💻 Просто о сложном: AtomicInteger

В многопоточном коде даже простая операция count++ не является атомарной. Она распадается на три шага:

1. Прочитать значение переменной.
2. Увеличить его.
3. Записать обратно.

Если два потока выполнят это одновременно, получится гонка данных (race condition). Итоговое значение будет меньше ожидаемого.

🟢Как решает проблему AtomicInteger

AtomicInteger — это класс из пакета java.util.concurrent.atomic, который предоставляет атомарные (неделимые) операции над целыми числами.

Под капотом он использует механизм CAS (Compare-And-Swap), который поддерживается на уровне процессора.

Принцип работы:
— Читаем текущее значение.
— Проверяем, не изменилось ли оно за это время.
— Если совпадает, записываем новое.
— Если нет, повторяем попытку (spin loop).

🟢Пример использования

public class Counter {
private final AtomicInteger count = new AtomicInteger(0);

public void increment() {
count.incrementAndGet(); // атомарное ++
}

public int get() {
return count.get();
}
}

Здесь incrementAndGet() гарантирует, что два потока не «перетрут» друг друга, а каждый инкремент будет учтён.

🟢Основные методы

🔘get() — получить текущее значение.
🔘set(int newValue) — установить новое значение.
🔘incrementAndGet() / getAndIncrement() — инкремент.
🔘decrementAndGet() — декремент.
🔘addAndGet(int delta) — прибавить значение.
🔘compareAndSet(int expect, int update) — вручную применить CAS.

🟢Подводные камни

— Спин-блокировки

CAS может крутиться в цикле, пока не удастся обновить значение. При высокой конкуренции это нагружает процессор.

— ABA-проблема

Значение могло измениться на «A → B → A». Для простых счётчиков это не критично, но в сложных структурах данных используют AtomicStampedReference.

— Ограниченность

AtomicInteger работает только с int. Для более сложных случаев есть AtomicLong, AtomicReference, LongAdder (оптимизирован для высокой конкуренции).

🟢Когда использовать

✔️ Подходит:

— Для простых счётчиков, метрик.
— В неблокирующих алгоритмах (lock-free).
— В высоконагруженных сценариях, где synchronized слишком дорог.

Не подходит:

— Для сложных бизнес-операций над несколькими переменными (лучше использовать мьютексы или транзакции).
— При очень высокой конкуренции, может быть лучше взять LongAdder.

🟢Итог

AtomicInteger — это лёгкий способ избавиться от гонок при работе с числами в многопоточности.

Это не магия, а всего лишь тонкая обёртка над CAS, встроенным в процессоры. Понимание этого механизма помогает писать по-настоящему безопасный и быстрый многопоточный код.

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍184🔥3
🕯 Паттерн Adapter (Адаптер)

Adapter — это структурный паттерн, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он действует как обёртка между двумя классами, приводя их интерфейсы к общему виду.

Использование:

🔹 Когда необходимо использовать сторонний код, который не соответствует ожидаемому интерфейсу.
🔹 Подходит для миграции систем, когда новые и старые классы должны работать вместе.
🔹 Для интеграции различных библиотек в проект без изменения их исходного кода.

Преимущества:

1️⃣ Устраняет зависимость от конкретных интерфейсов, облегчая дальнейшее развитие системы.
2️⃣ Позволяет легко адаптировать старый код к новым условиям, не затрагивая его исходный функционал.

Недостатки:

1️⃣ Увеличивает сложность системы за счёт введения дополнительных классов.
2️⃣ Может привести к увеличению времени выполнения программы при частом использовании.

📌 Часто используется при интеграции различных систем, например, при адаптации старого API для использования с новыми клиентами или библиотеками.

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥43
Media is too big
VIEW IN TELEGRAM
Создаём Telegram Бота с Нуля на Java и Spring Boot | Часть 1: Проектирование и Первые Шаги

Мы с вами вместе напишем реальный проект Telegram бота. Автор постарается в повествовательной, меньше технической, манере поведать вам об этапах разработки, поехали?

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🔥2
Media is too big
VIEW IN TELEGRAM
Создаём Telegram Бота с Нуля на Java и Spring Boot | Часть 2: Вырезка из процесса разработки

🖖Приветствую! Мы с вами вместе напишем реальный проект Telegram бота. В этой части я даю вам вырезку того, как проходит процесс.

Первая часть

📺🗣СМОТРЕТЬ RUTUBE

🌐🗣СМОТРЕТЬ VKVIDEO

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4🔥2
⚡️ Уровни изоляции транзакций в базах данных

В многопользовательских системах критически важно обеспечить согласованность данных при параллельных транзакциях. Одним из ключевых механизмов, который помогает в этом, являются уровни изоляции транзакций. Они регулируют, как обрабатываются изменения в данных при параллельной работе транзакций, предотвращая возможные аномалии.

🔑 Что такое изоляция транзакций?


Изоляция транзакций определяет степень, до которой операции в одной транзакции изолированы от операций в других. Это предотвращает такие проблемы, как грязные чтения, неповторяемые чтения и фантомные записи, обеспечивая целостность данных.

🔒 Типы уровней изоляции:

🔹 Read Uncommitted:
Самый низкий уровень изоляции. Транзакции могут читать изменения, сделанные другими транзакциями, даже если они не были зафиксированы (грязные чтения). Быстро, но рискованно.

🔹 Read Committed:
Видны только зафиксированные данные. Это исключает грязные чтения, но могут возникать неповторяемые чтения (данные меняются между двумя запросами).

🔹 Repeatable Read:

Гарантирует, что данные, прочитанные транзакцией, не могут быть изменены другой транзакцией до завершения первой. Однако возможны фантомные чтения (новые строки появляются при повторных запросах).

🔹 Serializable:
Самый высокий уровень изоляции. Полностью изолирует транзакцию, предотвращая грязные, неповторяемые и фантомные чтения. Однако это существенно снижает производительность.

Каждый уровень предлагает компромисс между производительностью и консистентностью данных. Более высокий уровень изоляции снижает конкурентоспособность, тогда как более низкий увеличивает риск возникновения аномалий. Важно правильно подобрать уровень в зависимости от требований приложения.

💬 Какой уровень изоляции вы чаще используете в своих приложениях?

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍124🔥2
👩‍💻 Java: Короткая задача

Задача:
Что выведет программа и почему?


public class Tricky {
public static void main(String[] args) {
System.out.println(getValue());
}

static int getValue() {
try {
return 1;
} finally {
return 2;
}
}
}


Разбор:

Блок finally всегда выполняется, даже если есть return в try.

Когда JVM встречает return 1;, она сохраняет значение для возврата.

Затем выполняет finally.

В finally есть новый return 2; — он перезаписывает сохранённый результат.

👉 Поэтому вернётся 2, а не 1.


Полезно знать:
Такое поведение часто ломает логику при работе с ресурсами - finally может изменить или "затереть" возвращаемое значение.
Лучше не использовать return внутри finally вообще.


Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥96
👀 Задачи с собеседований: Реализация метода equals() (middle)

- Как правильно переопределить метод equals()?

💡 Ключевые моменты:

▪️ Рефлексивность — объект должен быть равен самому себе.
▪️ Симметричность — если a.equals(b), то и b.equals(a) должно быть истинно.
▪️ Транзитивность — если a.equals(b) и b.equals(c), то a.equals(c) должно быть истинно.
▪️ Непротиворечивость — несколько вызовов метода equals() на одном и том же объекте должны возвращать одно и то же значение, если объекты не изменились.
▪️ null — вызов a.equals(null) должен возвращать false.

Реализация на картинке 👆

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍138🔥4
Микросервисы: как это на самом деле работает

В этом видео мы пошагово разберём, почему реальные корпоративные системы значительно сложнее учебных проектов, и как правильно строить архитектуру приложений.

В этом видео мы разбираемся:
• чем отличается "учебный" монолит от продакшн-системы;
• зачем нужна обсервабилити (метрики, логи, трейсы) и как её реализовать через Grafana, Prometheus, Loki, Tempo, Alloy;
• что такое деградация системы и как работают вертикальное и горизонтальное масштабирование;
• как реализовать распределённые транзакции с помощью паттерна Saga (оркестрация и хореография);
• как организовать безопасность с помощью Keycloak и API Gateway;
• как использовать OpenAPI + codegen для генерации DTO и Feign-клиентов;
• как настроить удобное окружение через Docker Compose + Makefile, Nexus и Spring Boot.

В практической части мы создадим микросервисную систему:

• сервис `person-service` для работы с пользователями;
• API Gateway для регистрации и аутентификации;
• интеграцию с Keycloak;
• аудит изменений (Hibernate Envers);
• инфраструктурный стек мониторинга и логирования.

В конце вы увидите полный цикл: запуск сервисов в Docker, проверка через Postman, метрики и трейсы в Grafana.

Это видео - полноценный практикум по построению микросервисной архитектуры с нуля.


🌐🗣СМОТРЕТЬ VKVIDEO

🎞🗣СМОТРЕТЬ YOUTUBE

Подписывайся на наш канал в Max 🟪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍163🔥3🎄1