fa
Feedback
Java | Фишки и трюки

Java | Фишки и трюки

رفتن به کانال در Telegram

Java: примеры кода, интересные фишки и полезные трюки Купить рекламу: https://telega.in/c/java_tips_and_tricks ✍️По всем вопросам: @Pascal4eg Менеджер по рекламе: @shmyzna

نمایش بیشتر
6 954
مشترکین
-724 ساعت
+117 روز
+830 روز
آرشیو پست ها
Гайд для маркетологов по эффективным онлайн-встречам Как CMO, PR и digital-маркетологам повысить результативность брейнштормо
Гайд для маркетологов по эффективным онлайн-встречам Как CMO, PR и digital-маркетологам повысить результативность брейнштормов, совещаний и планерок с командой с помощью онлайн-встреч? Гайд МТС Линк: 37 страниц полезных материалов, чек-листов и кейсов для эффективных видеовстреч и совещаний. ✅ В гайде: - Как создать постоянную ссылку на регулярные встречи с подрядчиками, командой или агентствами и подключаться в 2 клика; - Как управлять встречей и завершить ее четкими договоренностями с ИИ-расшифровкой голоса в текст; - Как проводить кастдевы, брейнштормы и формулировать гипотезы с помощью 15+ шаблонов в онлайн-досках МТС Линк; - Как разом пригласить всех участников на синк таким образом, чтобы все пришли. Бонус внутри: 5 способов не выгореть от бесконечных синков. ✨ Скачайте гайд бесплатно по ссылке Скачать #реклама 16+ mts-link.ru О рекламодателе

☕️Основные концепции ООП
В этом видео автор знакомит с фундаментальными принципами объектно-ориентированного программирования (ООП) на примере Java. Объясняется, для чего нужно ООП и каковы его ключевые концепции, без глубокого вникания в код.
🤩 Java Фишки и трюки || #Видео

🧪 Records с Validation: immutable данные с проверкой на входе В Java record — это идеальный инструмент для работы с неизменяемыми объектами. Но часто нам нужно не просто хранить данные, а проверять их корректность при создании. Хорошая новость: в record это встроено прямо в конструктор. 🔒 Простая неизменяемость
public record User(String name, int age) {}
➡️ Все поля final, сеттеров нет, объект полностью immutable. Но можно передать хоть отрицательный возраст — компилятор не остановит. ⚖️ Валидация в compact-конструкторе
public record User(String name, int age) {
    public User {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("Имя не может быть пустым");
        }
        if (age < 0) {
            throw new IllegalArgumentException("Возраст не может быть отрицательным");
        }
    }
}
➡️Такой конструктор автоматически вызывается при каждом new User(...), и данные сразу проверяются. 🛡 Гарантия на уровне модели
User u = new User("Иван", 25);   // ✅ всё ок
User bad = new User("", -5);     // ❌ IllegalArgumentException
➡️ Теперь ошибка «грязных данных» невозможна: объект даже не создастся. 🔄 Компактность vs. явный конструктор Можно написать и полный конструктор:
public User(String name, int age) {
    if (age < 18) throw new IllegalArgumentException("Только 18+");
    this.name = name;
    this.age = age;
}
➡️ Но компактная форма предпочтительнее — она короче и сразу показывает, что мы в record. 📦 Валидация коллекций внутри record
public record Order(List<String> items) {
    public Order {
        if (items == null || items.isEmpty()) {
            throw new IllegalArgumentException("Заказ пуст");
        }
        items = List.copyOf(items); // защитная копия
    }
}
➡️ Даже список внутри immutable — теперь никто не сможет изменить заказ после создания. 🚦 Использование с аннотациями Bean Validation
public record Customer(
    @NotBlank String name,
    @Email String email
) {}
➡️Если подключён Hibernate Validator или Jakarta Validation, поля проверятся автоматически. 🧩 Кейс: «валидный объект» как контракт
public record Email(String value) {
    public Email {
        if (!value.matches("^[\\w.-]+@[\\w.-]+\\.[a-z]{2,}$")) {
            throw new IllegalArgumentException("Некорректный email");
        }
    }
}
➡️ Теперь в коде невозможно передать «плохую строку» туда, где нужен Email. 🗣️ Запомни: record — это не просто сокращённый POJO, а мощный способ гарантировать неизменяемость и корректность данных ещё при создании объекта.

🤔 Слишком поздно заходить в IT в 2025? Врать не буду: скорее да, чем нет — за последние пять лет порог вхождения сильно поднялся, и теперь нередко от джуна требуют навыки грейдом выше. Что делать в такой ситуации? Учиться эффективнее остальных и знать, как подать себя на рынке других. Разобраться со всем этим вам поможет База Знаний — мест, где за вас уже отобрали лучшие материалы по самым востребованным вакансиям: 🖥 Python Dev: 1558+ материалов 👩‍💻 Frontend Dev: 1241+ материалов 👩‍💻 Backend Dev: 1095+ материалов 📊 Data Scientist: 978+ материалов 🎨 UX/UI Designer: 885+ материалов 📖 Книги по IT: 779+ материалов Советую перейти и начать учиться уже сейчас — так уже к осени сможете претендовать на вакансию c хорошим окладом 👍

🧩 Sealed Classes — контроль наследования в Java Java 17 принесла sealed classes — способ держать наследование под контролем. Больше никаких «кто угодно расширил класс и сделал фигню». Теперь ты сам решаешь, кто может быть наследником. 📦 Базовый sealed-класс

public sealed class Shape 
    permits Circle, Rectangle, Triangle {}
➡️ Только три класса могут расширять Shape. 🔑 Наследники обязаны выбрать модификатор

public final class Circle extends Shape {}
public non-sealed class Rectangle extends Shape {}
public sealed class Triangle extends Shape 
    permits Equilateral, Isosceles {}
🟢 final — тупик, дальше наследовать нельзя. 🟢 sealed — можно, но только по твоему списку. 🟢 non-sealed — снимает ограничения, разрешает наследование всем. 🧠 Идеально для switch

static String type(Shape s) {
    return switch (s) {
        case Circle c    -> "Окружность";
        case Rectangle r -> "Прямоугольник";
        case Triangle t  -> "Треугольник";
    };
}
➡️ Компилятор знает все варианты и не требует default. Ты не забудешь обработать новый тип. 🛠 Контроль API

public sealed interface Request 
    permits Login, Register, Ping {}

public final class Login implements Request {}
public final class Register implements Request {}
public final class Ping implements Request {}
➡️ Никто не добавит лишний «левый» запрос. Архитектура закрыта и прозрачна. 📚 Отличие от abstract
🟢abstract оставляет свободу: наследников сколько угодно. 🟢sealed фиксирует список: никакой самодеятельности.
➡️ Это не про обязательные методы, а про ограничение иерархии. 🧱 Комбо с record

public sealed interface Shape permits Circle, Rectangle {}

public record Circle(double r) implements Shape {}
public record Rectangle(double w, double h) implements Shape {}
➡️ Получаешь компактные immutable-модели и полную предсказуемость. 🗣️ Запомни: Используй в API, моделях и ролях, где важна безопасность и прозрачность.

👩‍💻 Всем программистам посвящается! Вот 17 авторских обучающих IT каналов по самым востребованным областям программирования
👩‍💻 Всем программистам посвящается! Вот 17 авторских обучающих IT каналов по самым востребованным областям программирования: Выбирай своё направление: 👩‍💻 Java — t.me/java_ready 👩‍💻 Python — t.me/python_ready 🤔 InfoSec & Хакинг — t.me/hacking_ready 🖥 SQL & Базы Данных — t.me/sql_ready 🤖 Нейросетиt.me/neuro_ready 👩‍💻 C/C++ — https://t.me/cpp_ready 👩‍💻 C# & Unity — t.me/csharp_ready 👩‍💻 Linux — t.me/linux_ready 🖼️ DevOpst.me/devops_ready 📖 IT Книги — t.me/books_ready 👩‍💻 Frontend — t.me/frontend_ready 📱 JavaScript — t.me/javascript_ready 👩‍💻 Backend — t.me/backend_ready 📱 GitHub & Git — t.me/github_ready 👩‍💻 Весь IT — t.me/it_ready 👩‍💻 Bash & Shell — t.me/bash_ready 🖥 Design — t.me/design_ready 📌 Гайды, шпаргалки, задачи, ресурсы и фишки для каждого языка программирования!

ZGC 🆚 Shenandoah — битва без стоп-пауз Java в 2025 уже умеет два монстра low-latency GC: ZGC и Shenandoah. Оба обещают микросекундные паузы даже на кучах в сотни гигабайт. Но у каждого свой характер. Давай разберёмся. 📦 Запуск ZGC (JDK 15+):
java -XX:+UseZGC -Xmx16g -Xms16g -jar app.jar
Shenandoah (JDK 12+, лучше JDK 17+):
java -XX:+UseShenandoahGC -Xmx16g -Xms16g -jar app.jar
➡️ Оба вкл/выкл одним флагом. 🧠 Архитектура под капотом 🔵 ZGC:
🟢Использует colored pointers (цветные указатели в 64-битных адресах). 🟢Разносит паузы на микросекундные stop-the-world (STW). 🟢Очень простая логика: mark → relocate, всё конкурентно.
🔴 Shenandoah:
🟢Делает concurrent compacting: сжимает кучу без паузы. 🟢Использует brooks pointers (доп. уровень индирекции → каждый объект указывает на forwarder). 🟢Чуть медленнее из-за этой индирекции, но тоже держит паузы \~<10мс.
⚙️ Пример приложения для сравнения
import java.util.ArrayList;
import java.util.List;

public class StressTest {
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        while (true) {
            for (int i = 0; i < 100; i++) {
                list.add(new byte[1024 * 1024]); // 100MB
            }
            if (list.size() > 2000) list.clear(); // держим heap живым
        }
    }
}
📊 Запускаем и смотрим логи 🔵 ZGC (-XX:+UseZGC -Xlog:gc*):
[2.345s][info][gc] GC(7) Pause Mark Start 0.2ms
[2.345s][info][gc] GC(7) Pause Mark End 0.1ms
[2.346s][info][gc] GC(7) Concurrent Relocate 45.6ms
➡️ Паузы \~0.1–0.3 мс. Основная работа уходит в «Concurrent Relocate», но это в фоне. 🔴 Shenandoah (-XX:+UseShenandoahGC -Xlog:gc*):
[2.456s][info][gc] Pause Init Mark 1.2ms
[2.457s][info][gc] Concurrent Mark 38.9ms
[2.496s][info][gc] Pause Final Evac 1.5ms
➡️ Паузы больше (1–2 мс), но всё ещё очень маленькие. 🧪 Реальные различия (TL;DR)
Характеристика        | ZGC 🟢                       | Shenandoah 🔴
--------------------  | ---------------------------- | ----------------------------
⏱️ Паузы (latency)   | ~0.2–2 мс (супер-стабильно) | ~1–10 мс (чуть длиннее)
⚡️ Throughput        | Чуть выше (нет индирекции)  | Чуть ниже (Brooks ptr)
🗂 Heap size         | До 16 ТБ (!)                | Ограничен ~4–8 ТБ
🧩 Сложность         | Простая модель              | Более гибкий, но сложнее
🎯 Подходит для      | Trading, real-time API      | Крупные JVM-сервисы, где не критичны 2–3 мс
🎯 Выводы 👍 ZGC → если нужна ультра-низкая задержка (финтех, realtime). Работает предсказуемо. 👍 Shenandoah → если heap до пары терабайт и важнее гибкость (много опций тюнинга). 🗣️ Запомни: ZGC = хирург с лазером, точный и быстрый.Shenandoah = механик с инструментами, чуть дольше, но чинит даже сложные ситуации.В продакшене пробуй оба — профит зависит от нагрузки и архитектуры.

ИТ-специалисты Петербурга, общий сбор 6 и 7 сентября пройдет ИТ-фестиваль «Сезон кода» для опытных разработчиков, ML-инженеро
ИТ-специалисты Петербурга, общий сбор  6 и 7 сентября пройдет ИТ-фестиваль «Сезон кода» для опытных разработчиков, ML-инженеров, архитекторов, специалистов по информационной безопасности и других ИТ-специалистов. Спикеры из Т-Банка и других компаний зовут слушать доклады, обмениваться опытом и знакомиться с единомышленниками. Развлечения и музыка тоже будут.  В первый день: — Разберетесь в архитектуре систем, надежности и работе с данными.  — Узнаете, как технологии помогают решать задачи клиентов и бизнеса. — Поймете, как идеи становятся инструментами и продуктами. Во второй день:  — Услышите про актуальные подходы к обеспечению информационной безопасности в разработке. — Узнаете про backend-принципы, которые помогают работать эффективнее. — Увидите, как работают LLM и куда все это движется. Выбирайте один из дней или посетите оба. Встреча пройдет в новом ИТ-хабе Т-Технологий в Санкт-Петербурге. Успейте зарегистрироваться до 5 сентября

⚡️ Reactive Streams: поток вместо цикла — и это работает В обычном Java-коде всё блокируется: запрос ждёт ответ, поток простаивает. В реактивщине (Spring WebFlux) — данные текут как река. Ты подписался на поток → получил элементы по мере готовности. 📛 Пример: возвращаем поток данных
import reactor.core.publisher.Flux;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @GetMapping("/users")
    public Flux<String> getUsers() {
        return Flux.just("Alice", "Bob", "Charlie");
    }
}
➡️ Не List, а Flux. Клиент получит поэлементно: Alice → Bob → Charlie. 🔄 Mono vs Flux 👍 Mono<T> → 0..1 элемент 👍 Flux<T> → 0..N элементов
@GetMapping("/user")
public Mono<String> getUser() {
    return Mono.just("Alice");
}
➡️ Реактивщина различает одиночный результат и поток. 🧪 Преобразования прямо в цепочке
Flux.range(1, 5)
    .map(i -> i * 2)
    .filter(i -> i > 5)
    .subscribe(System.out::println);
➡️ Поток как коллекция, но лениво и неблокирующе. 📦 Асинхронные запросы
@GetMapping("/external")
public Mono<String> callApi(WebClient client) {
    return client.get()
                 .uri("https://api.example.com/data")
                 .retrieve()
                 .bodyToMono(String.class);
}
➡️ Без блокировок. Пока API думает — поток свободен для других задач. 🔗 Комбинация потоков
Mono<String> u1 = Mono.just("Alice");
Mono<String> u2 = Mono.just("Bob");

Flux<String> merged = Flux.merge(u1, u2);
➡️ Потоки объединяются — результат приходит как готов. 👀 Backpressure (контроль скорости)
Publisher шлёт данные → Subscriber сам говорит, сколько готов принять. Нет перегрузки, система держится даже при большом потоке событий.
🗣️ Запомни: Не блокируйся на ожидании. Подписывайся, фильтруй и трансформируй.

☕️ Коллекции в Джава (Collections Framework)
В этом видео автор подробно объясняет, как работает Collections Framework в Java. Пошагово демонстрируются основные интерфейсы и реализации: List, Set, Map, а также важные классы вроде ArrayList, HashSet, HashMap. Показано, как правильно выбирать подходящую коллекцию, когда использовать список, а когда — отображение, как добавлять, удалять и перебирать элементы.
🤩 Java Фишки и трюки || #Видео

🧹 Advanced GC Tuning — ZGC в Java Если ты думаешь, что GC — это просто «собрал мусор и пошёл дальше», то добро пожаловать в ад продакшена с кучей тредов и 200 ГБ heap’а. Обычный GC может стопнуть мир на секунду — и твой сервис превращается в «слайдшоу». Для маркетплейса или финтеха — смерть. Тут на сцену выходит ZGC — сборщик мусора, который обещает паузы меньше 1 мс, даже на огромных хипах. 📦 Как включить ZGC Запускаешь Java-приложение с флагами:
java -XX:+UseZGC -Xmx16g -Xms16g -jar app.jar
➡️ -XX:+UseZGC активирует Z Garbage Collector. ➡️ Работает начиная с JDK 11 (продакшен-стабил с 15). 🧠 В чём магия ZGC? Обычный GC работает так: стопнул мир → пересобрал кучу → отпустил. ZGC же:
🟢 Делает конкурентную маркировку и компактификацию (почти весь GC идёт параллельно с твоим кодом). 🟢 Использует цветные указатели (colored pointers), чтобы отслеживать состояние объектов. 🟢 Работает без длинных стопов — паузы \~0.5–2 мс даже при 100+ ГБ heap.
➡️ Идеален для real-time систем, API с миллионами RPS, финансовых транзакций. ⚙️ Настройки для тюнинга Базовые:
-XX:+UseZGC
-XX:ZUncommitDelay=300
-XX:SoftMaxHeapSize=12g
🟢 ZUncommitDelay — через сколько секунд освобождать неиспользуемую память (по умолчанию 300). 🟢 SoftMaxHeapSize — мягкий лимит кучи (GC будет стараться держаться в нём, даже если Xmx больше).
Мониторинг:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintGC -Xlog:gc*:gc.log
➡️ Логи GC покажут, как часто идут паузы и сколько памяти реально отжимается. 🔍 Пример GC-лога с ZGC
[2.345s][info][gc,start    ] GC(0) Pause Mark Start
[2.345s][info][gc          ] GC(0) Concurrent Mark
[2.348s][info][gc          ] GC(0) Pause Mark End 0.2ms
[2.349s][info][gc          ] GC(0) Concurrent Relocate
➡️ Видишь? Паузы меньше миллисекунды, всё остальное уходит в concurrent. Когда брать ZGC, а когда нет 🟢 Бери:
🟢 У тебя огромные хипы (16–500 ГБ). 🟢 Важны низкие latency (игры, трейдинг, API). 🟢 Ты не хочешь тратить дни на ручной тюнинг старых GC.
🔴 Не бери:
🟢Если у тебя микросервис на 512 МБ heap (Overkill). 🟢Если нужен максимальный throughput (G1 иногда быстрее на маленьких heap’ах).
🗣️ Запомни:Он не делает чудес — память всё равно надо оптимизировать, но он гарантирует, что GC-паузы не убьют твой SLA.

Сложные вопросы с собесов Найден годный Telegram-бот для прокачки скиллов по Java, Spring, Kafka, Postgres и микросервисам: @
Сложные вопросы с собесов Найден годный Telegram-бот для прокачки скиллов по Java, Spring, Kafka, Postgres и микросервисам: @awesome_java_mentor_bot Каждый день бот шлёт вопросы с реальных собесов на Middle/Senior позицию. Если не знаешь ответ - есть пояснения, шикарная база знаний и ссылки на доп.материалы Переходим👉 @awesome_java_mentor_bot  Реклама. Яковлева Д.А. ИНН 781147324623. erid: 2W5zFJYXyXN

☕️ Массивы данных. Одномерные и многомерные массивы
В этом видео разбираются основы работы с массивами в Java. Автор показывает, как создавать и использовать одномерные и многомерные массивы, как обращаться к их элементам и перебирать данные. Это базовый инструмент, без которого невозможно работать с большими наборами информации.
🤩 Java Фишки и трюки || #Видео

⚡️ Reactive Streams в Java — WebFlux + Project Reactor Когда у тебя миллион запросов и сервер начинает задыхаться — обычный Spring MVC с потоками умирает. Тут выходит на сцену Spring WebFlux и движок Project Reactor. Асинхронщина, backpressure, и код, который реально дышит под нагрузкой. 📦 Подключаем WebFlux в pom.xml:
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
➡️ Всё. Теперь у тебя вместо старого DispatcherServlet — реактивный движок Netty. 🧠 Минимальный контроллер на WebFlux:
@RestController
public class HelloController {
    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("👋 Привет, реактивный мир!");
    }
}
➡️ Mono = 0..1 значение (как Future). Flux = поток значений. 📛 Пример со стримом чисел:
@GetMapping("/numbers")
public Flux<Integer> numbers() {
    return Flux.range(1, 5).delayElements(Duration.ofSeconds(1));
}
➡️ Клиент получает числа по одному каждую секунду. Не JSON сразу, а настоящий поток. 🔄 Реактивные операторы (Project Reactor):
Flux.just("A", "B", "C")
    .map(s -> s.toLowerCase())
    .filter(s -> !s.equals("b"))
    .subscribe(System.out::println);
➡️ Конвейер: map → filter → подписка. Реактивщина — это не if’ы и for, а цепочки. 💥 Backpressure — контроль нагрузки:
Flux.interval(Duration.ofMillis(10))
    .onBackpressureDrop()
    .subscribe(i -> System.out.println("⚡️ " + i));
➡️ Если потребитель не успевает — лишние данные отбрасываются. Ты управляешь потоком, а не он тобой. 🔐 Интеграция с БД через R2DBC:
@Repository
public interface UserRepo extends ReactiveCrudRepository<User, String> {}

@GetMapping("/users")
public Flux<User> getUsers() {
    return userRepo.findAll();
}
➡️ Даже база работает реактивно. Никаких блокировок потоков. Чем отличается WebFlux 🆚 Project Reactor?
👍 Project Reactor = библиотека реактивных стримов (Mono, Flux, операторы). 👍 WebFlux = фреймворк на базе Reactor, чтобы писать контроллеры, API и сервисы.
📚 Документация:
👉 Reactor 👈 👉 WebFlux 👈
🗣️ Запомни: Reactive Streams — это не магия ради хайпа. Это способ выжить под нагрузкой, где обычный синхронный код падает. Если хочешь сервер, который тащит десятки тысяч соединений — без WebFlux и Reactor ты уже динозавр.

🔥 Самые нужные каналы для Java разработчика, чтобы расти в доходе 💸Java | Вопросы собесовJava | Вакансии с удаленкойJava | LeetCodeJava | Тесты Подпишись, чтобы не потерять ☝️

☕️Distributed Tracing — Zipkin без боли Когда у тебя микросервисы, баги превращаются в квест.
Клиент сделал запрос ➡️ прошёл через API ➡️ сервис авторизации ➡️ сервис платежей ➡️ сервис нотификаций. А потом где-то что-то упало. Где искать? Логов тонны, grep не спасает.
Тут появляется Zipkin — Sherlock Holmes твоей системы. 📦 Поднять Zipkin проще простого Через Docker:
docker run -d -p 9411:9411 openzipkin/zipkin
➡️ Открываешь [http://localhost:9411](http://localhost:9411) — готово. У тебя веб-интерфейс для трассировок. 🧠 Как это работает Zipkin использует концепцию trace и span:
🟢trace = весь путь запроса от начала до конца 🟢span = отдельный шаг внутри пути (запрос к БД, вызов другого сервиса)
Каждый сервис при вызове следующего передаёт trace-id и span-id в заголовках (обычно X-B3-TraceId, X-B3-SpanId). ➡️ В итоге: в UI ты видишь красивую диаграмму, где висит каждый шаг. ⚙️ Интеграция в Spring Boot Добавляешь зависимости:
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
А в application.yml:
spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0
➡️ Теперь каждый запрос автоматически получает trace-id, а все логи будут содержать [traceId, spanId]. 🔍 Пример лога
2025-08-22 12:42:01 [traceId=4af3, spanId=1a2b] Calling PaymentService
➡️ Видишь traceId? Теперь ты можешь в Zipkin найти все вызовы, связанные с этим запросом. 🎯 Зачем это реально нужно
👍 🕵️ Находить медленные места (Bottlenecks) 👍 🐛 Локализовать баг в цепочке сервисов 👍 📊 Смотреть статистику по задержкам и ошибкам
🗣️ Запомни: В микросервисах без трассировки ты как водитель без фар ночью.

⌨️ StringJoiner - это класс, который предназначен для объединения строк с использованием разделителя между ними. Этот класс был введен в Java 8 в пакете java.util. Он облегчает создание текстовых последовательностей, объединяя строки и вставляя разделители между ними. Вызов метода toString() возвращает объединенную строку с разделителями и окружающими символами. Вы также можете использовать метод setEmptyValue() для определения значения, которое будет использоваться, если StringJoiner остается пустым.

StringJoiner sj = new StringJoiner(", ", "[" , "]");
sj.setEmptyValue("No items");
System.out.println(sj.toString()); // No items

sj.add("Apple").add("Banana").add("Cherry");
System.out.println(sj.toString()); // [Apple, Banana, Cherry]
#java #StringJoiner

⌨️ Дженерики (generics) — это механизм, который позволяет создавать классы, интерфейсы и методы, работающие с различными типами данных, при этом сохраняя строгую типизацию. Они были введены в Java начиная с версии 5 для повышения безопасности типов и повторного использования кода. Дженерики позволяют определить параметр типа, который будет заменен конкретным типом данных при создании экземпляра класса или вызове метода. Например, List<T> может использоваться как List<String>, List<Integer> и т.д. Благодаря дженерикам, ошибки типа (например, попытка вставить объект неправильного типа) обнаруживаются на этапе компиляции, а не во время выполнения программы. Один универсальный класс или метод может работать с различными типами данных, что позволяет избежать дублирования кода. Во время компиляции информация о типах стирается, и вместо этого используется базовый тип, что позволяет сохранять совместимость с кодом, написанным до появления дженериков.

public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}

Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
String str = stringBox.getItem();
В этом примере класс Box<T> является обобщенным и может работать с любым типом данных, который заменит T при создании объекта. #java #generics #T

☕️Условные конструкции (if-else, switch-case)
Это видео объясняет, как работают условные операторы в Java. Ты узнаешь, как с помощью if, else if, else и switch-case принимать решения в коде и управлять логикой программы.
🤩 Java Фишки и трюки || #Видео

☕️ ArrayList & HashMap: быстрые коллекции, которые решают всё В Java массивы — фиксированные, а коллекции умеют расти, менять размер и работать с разными типами данных. ArrayList и HashMap — два столпа, на которых держатся 80% задач. 🔢. Создание и добавление
import java.util.ArrayList;

ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
👉 ArrayList хранит элементы в порядке добавления и умеет расти автоматически. 🔢. Доступ по индексу
String lang = list.get(0);
System.out.println(lang); // Java
👉 Как в массиве: быстрый доступ по номеру, но индекс должен быть в пределах размера. 🔢. Перебор элементов
for (String l : list) {
    System.out.println(l);
}
👉 Удобный синтаксис for-each для чтения всех значений без возни с индексами. 🔢. HashMap: хранение по ключу
import java.util.HashMap;

HashMap<String, Integer> map = new HashMap<>();
map.put("Apples", 5);
map.put("Oranges", 3);
👉 HashMap — это ключ-значение. Ключи уникальны, значения можно повторять. 🔢. Получение по ключу
int count = map.get("Apples");
System.out.println(count); // 5
👉 Быстрое извлечение: доступ почти моментальный. 🔢. Проверка наличия
if (map.containsKey("Oranges")) {
    System.out.println("Есть апельсины!");
}
👉 Нет ключа — вернёт false, а не ошибку. 🗝 🔢. Перебор пар
for (var entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
👉 Легко пройтись сразу и по ключам, и по значениям. 🗣️ Запомни: массивы — это база, но ArrayList и HashMap дают гибкость. Используй массивы, когда важна скорость и фиксированный размер, а коллекции — когда нужно удобно, динамично и без лишней возни.