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

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

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

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

نمایش بیشتر
6 964
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+557 روز
+2130 روز
آرشیو پست ها
⌨️ equals() и hashCode() - почему они ломают коллекции (и как это исправить) Одна из самых коварных тем в Java — это контракт между equals() и hashCode(). Ошибся и HashMap или HashSet начинают вести себя "магически" (читай: ломаются). 📦 Проблема на практике

Set<User> users = new HashSet<>();

users.add(new User("Alex"));
System.out.println(users.contains(new User("Alex"))); // ❌ false
🤨 Почему false, если значения одинаковые? ⚠️ Причина По умолчанию equals() сравнивает ссылки (==), а не содержимое. ✅ Правильная реализация

public class User {
    private String name;

    // equals
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }

    // hashCode
    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}
🔥 Почему важны ОБА метода? Если переопределить только equals():

users.add(new User("Alex"));
users.contains(new User("Alex")); // ❌ всё ещё может быть false
👉 Потому что HashSet сначала смотрит на hashCode(), а потом уже на equals(). ⚡ Контракт, который нельзя нарушать 1. Если equals() возвращает truehashCode() обязан быть одинаковым 2. Если hashCode() одинаковый → equals() может быть как true, так и false 💣 Классическая ошибка Изменяем объект после добавления в HashSet:

User user = new User("Alex");
users.add(user);

user.setName("Bob");

users.contains(user); // ❌ может вернуть false
👉 Объект "потерялся" в коллекции 🧠 Как избежать проблем * Делай объекты immutable (final поля) * Используй record (Java 16+):

public record User(String name) {}
👉 equals() и hashCode() генерируются автоматически и корректно 📌 Вывод Коллекции в Java работают быстро благодаря hashCode(), но требуют строгого соблюдения контракта. Нарушишь - получишь баги, которые очень сложно отловить 🐛

На собес в Сбер — 60 минут, live-coding и SQL прямо на камеру. Знаешь, что спросят? Мы знаем. И выложили. @Java Jub — Java-ва
На собес в Сбер — 60 минут, live-coding и SQL прямо на камеру. Знаешь, что спросят? Мы знаем. И выложили. @Java Jub — Java-вакансии + реальные вопросы, задачи и стек к каждой. 📱 Переходи: Java Jub (Job)

⌨️ Ленивая инициализация через `Supplier` - мощнее, чем кажется В Java есть недооценённая фишка - ленивые вычисления через Supplier. Это может сильно упростить код и улучшить производительность. 📦 Что такое `Supplier`? Это функциональный интерфейс из java.util.function, который просто возвращает значение:

Supplier<String> supplier = () -> "Hello";
System.out.println(supplier.get());
Но магия начинается, когда используешь его правильно 👇 🔥 Кейс: дорогое вычисление

public String getData() {
    System.out.println("Loading...");
    return "data";
}
Теперь сравни: ❌ Обычный вызов:

String result = getData(); // всегда выполняется
✅ Ленивый вызов:

Supplier<String> supplier = this::getData;

// вызов произойдёт только здесь
String result = supplier.get();
👉 Код выполняется только когда реально нужен результат. ⚡ Практическое применение: логирование

logger.debug("Result: " + expensiveOperation());
❗ Даже если debug выключен — expensiveOperation() всё равно выполнится. ✅ Правильно:

logger.debug(() -> "Result: " + expensiveOperation());
👉 Вычисление произойдёт только если лог реально пишется. 🧠 Комбинация с `Optional`

String name = Optional.ofNullable(getName())
                      .orElseGet(() -> generateDefaultName());
👉 generateDefaultName() вызовется только если значение отсутствует (в отличие от orElse, который выполняется всегда) 🚀 Паттерн: кэширование (lazy cache)

Supplier<String> cached = new Supplier<>() {
    private String value;

    @Override
    public String get() {
        if (value == null) {
            value = loadExpensiveData();
        }
        return value;
    }
};
👉 Получаешь простую ленивую инициализацию без лишних библиотек 📌 Вывод Supplier — это не просто "лямбда ради лямбды", а инструмент для: * ленивых вычислений * оптимизации * более чистого API

Играй и выигрывай промокоды на 20 000 рублей! Тот момент, когда в игре ❤️❤️❤️ закончились, а ответ на вопрос не знаешь! Точно нужна помощь друзей, родных, девочек, Вани и Аннушки вместе взятых! Тем более, когда на кону промокоды по 20 000 рублей на покупки в Спортмастере... Ждем тебя: Переходи в бота, следуй инструкциям и запускай игру Создавай своего персонажа и выбирай, на чем он будет гонять Управляй наклоном телефона и докажи, кто здесь главный гонщик Топ-10 лучших игроков получат промокоды по 20 000 рублей, чтобы экипироваться к новому сезону на колёсах. Играем до 30 апреля, погнали! Перейти на сайт #реклама 16+ О рекламодателе

🌱 Spring Cloud Config — это проект в экосистеме Spring, который предоставляет сервер и клиент для централизованного управления конфигурацией в распределённых системах. Основная идея Spring Cloud Config — это вынесение конфигурационных файлов из приложений в единое место (например, репозиторий Git), чтобы облегчить управление конфигурацией для различных сервисов в микросервисной архитектуре. Основные компоненты ✔️ Config Server — сервер, который хранит конфигурации (обычно в Git) и раздает их микросервисам. ✔️ Config Client — клиент в микросервисах, который получает конфигурации от Config Server. Возможности ✔️ Централизация конфигураций всех сервисов. ✔️ Поддержка версионирования конфигураций (например, через Git). ✔️ Динамическое обновление конфигураций без перезапуска приложений с помощью Spring Cloud Bus. ✔️ Поддержка различных сред и профилей (dev, prod и т.д.). Пример настройки Config Server:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-repo/config-repo
Пример настройки Config Client:

spring:
  cloud:
    config:
      uri: http://localhost:8888
      profile: dev
Преимущества: упрощает управление конфигурациями, поддерживает разные среды, позволяет динамически обновлять настройки. Недостатки: важен контроль за доступом и стабильностью Config Server. #java #Spring #Cloud #Config

🔴 Завтра тестовое собеседование с Java-разработчиком 15 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесе
🔴 Завтра тестовое собеседование с Java-разработчиком 15 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Виктору Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

🔗 В чем разница между == и .equals()? При сравнении объектов в Java важно понимать различие между == и .equals(). ✔️ == сравнивает ссылки на объекты, проверяя, указывают ли они на одну и ту же область памяти. ✔️ .equals() используется для сравнения содержимого объектов, если метод переопределен. Пример:
String a = new String("Java");
String b = new String("Java");

System.out.println(a == b); // false (разные ссылки)
System.out.println(a.equals(b)); // true (сравнение содержимого)
💡 Совет: для корректного сравнения объектов всегда переопределяйте метод equals() в вашем классе. #java #equals #comparison

В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн Но где их находить? Как узнавать о них ран
В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн Но где их находить? Как узнавать о них раньше, чем когда все начнут выкладывать фотографии оттуда? Переходите на канал IT-Мероприятия России. В нём каждый день анонсируются мероприятия со всех городов России 📆 в канале размещаются как онлайн, так и оффлайн мероприятия; 👩‍💻 можно найти ивенты по любому стеку: программирование, frontend-backend разработка, кибербезопасность, дата-аналитика, osint, devops и другие; 🎙 разнообразные форматы мероприятий: митапы с коллегами по цеху, конференции и вебинары с известными опытными специалистами, форумы и олимпиады от важных представителей индустрии и многое другое А чтобы не искать по разным форумам и чатам новости о предстоящих ивентах: 🚀 IT-мероприятия Россииподписывайся и будь в курсе всех предстоящих мероприятий!

🖥 Блоки инициализации в Java Блоки инициализации позволяют гибко управлять созданием объектов. Вот как их правильно использовать: 💠 Нестатические блоки Выполняются перед конструктором:
public class Logger {
    private String prefix;
    
    { // Блок инициализации экземпляра (выполняется перед конструктором)
        prefix = "[LOG] " + LocalDateTime.now();  // Инициализация префикса с текущей датой/временем
        System.out.println("Логгер готов!");      // Сообщение о готовности логгера
    }
    
    public Logger() {
        System.out.println(prefix + " | Новый объект");  // Вывод информации о создании объекта
    }
}
Для чего: предварительная настройка полей, валидация, логирование. 💠 Статические блоки Срабатывают один раз при загрузке класса:
public class ConfigLoader {
    static {
        System.out.println("Загружаем конфиги...");
        // Здесь можно читать файлы, подключать БД и т.д.
    }
}
Для чего: инициализация кэшей, регистрация драйверов, загрузка ресурсов. 📝 Когда что использовать - Нестатические блоки → простая инициализация полей - Статические блоки → настройка системных ресурсов 🧬Дополнение: Для улучшения читаемости кода используйте блоки инициализации для простых операций. Избегайте сложной логики — это может затруднить отладку и понимание приложения.

0% налогов и легальный Stripe для IT Ищете надежную базу для масштабирования IT-компании? Откройте бэк-офис в ведущем IT-хабе
+4
0% налогов и легальный Stripe для IT Ищете надежную базу для масштабирования IT-компании? Откройте бэк-офис в ведущем IT-хабе Центральной Азии. Статус резидента IT Park дает четкие преимущества: 0% налогов: полное освобождение от налога на прибыль, социалку и НДС (экспорт). 7.5% НДФЛ: минимальная ставка для ваших сотрудников. Финтех-интеграция: легальная работа со Stripe, PayPal и мировыми банками. Скорость: регистрация юрлица и получение статуса удаленно за 10 дней. Более 1000 международных компаний уже ведут глобальный бизнес через Узбекистан. Оставьте заявку и получите бесплатную консультацию: Получить консультацию #реклама outsource.gov.uz О рекламодателе

⌨️ Срезы в стримах. Метод takeWhile В Java 9 появилось два новых метода, полезных для выбора элементов потока с хорошей производительностью: takeWhile и dropWhile. Допустим, у нас есть следующий список блюд:

List<Dish> specialMenu = Arrays.asList(
new Dish("seasonal fruit", 120),
new Dish("prawns", 300),
new Dish("rice", 350),
new Dish("chicken", 400),
new Dish("french fries", 530));
Для получения блюд с калорийностью меньше 320, можно воспользоваться операцией filter. Недостаток операции filter в том, что она требует прохода в цикле по всему потоку данных с применением предиката ко всем элементам. В нашем примере список уже отсортирован по числу калорий. Вместо того, чтобы пройтись по каждому элементу, можно прекратить работу сразу же после обнаружения блюда, содержащего 320 калорий или более. В случае небольшого списка это может показаться не таким уж громадным преимуществом, но при работе с потенциально большим потоком элементов окажется весьма полезным. Поможет нам в этом операция takeWhile! Она позволяет выполнить срез любого потока данных (даже бесконечного) с помощью предиката. И, к счастью, она прекращает работу сразу же по обнаружении неподходящего элемента. Вот как ее следует использовать:

List<Dish> sliceMenu1 
    = specialMenu.stream()
                 .takeWhile(dish -> dish.getCalories() < 320)
                 .collect(toList());
#java #stream #takeWhile

🚗 Готовишься к экзамену в ГИБДД? Попробуй удобное Android-приложение для изучения ПДД и решения билетов: 👉 https://play.goo
🚗 Готовишься к экзамену в ГИБДД? Попробуй удобное Android-приложение для изучения ПДД и решения билетов: 👉 https://play.google.com/store/apps/details?id=com.pascal4eg.pdd Что внутри: ✔️ Актуальные правила и штрафы ✔️ Новые экзаменационные билеты ✔️ Режим экзамена — как в ГИБДД ✔️ Лёгкое приложение — всего 30 МБ 🌙 Тёмная тема для комфортного обучения Готовься к экзамену быстро и без лишнего стресса!

⌨️ Какими значениями инициализируются переменные по умолчанию?

byte — (byte)0;
short — (short)0;
int — 0;
long — 0L;
float — 0f;
double — 0d;
char — \u0000;
boolean — false;
Объекты (в том числе String) — null.
#java #initialization

⌨️ Чтение и запись файла с помощью класса Files Чтение всего файла в список строк (readAllLines)

import java.nio.file.*;
import java.io.IOException;
import java.util.List;

public class Main {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("example.txt");
        List<String> lines = Files.readAllLines(path);
        lines.forEach(System.out::println);
    }
}
📌 Читает весь файл в List<String>, удобно для небольших файлов. Запись в файл (write)

List<String> lines = List.of("Первая строка", "Вторая строка");
Files.write(Paths.get("output.txt"), lines);
📌 Если файла нет — создаст, если есть — перезапишет. Добавление в файл (без перезаписи):

Files.write(Paths.get("output.txt"), lines, StandardOpenOption.APPEND);
#java #Files #readAllLines #write

🔴 Завтра тестовое собеседование с Java-разработчиком 1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесед
🔴 Завтра тестовое собеседование с Java-разработчиком 1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Виктору Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

⌨️ JVM Escape Analysis: Миф о том, что все объекты живут в Куче (Heap) Вспомните свои первые уроки по Java. Нам всем говорили: "Примитивы (int, double) живут в быстром Стеке (Stack), а вот объекты (new Object()) всегда создаются в медленной Куче (Heap), и потом за ними приходит Garbage Collector". Спойлер: В некоторых случаях JVM может вообще не создавать объект в heap Создание объекта в Heap не бесплатно. Нужно выделить память, синхронизировать потоки, а потом еще и напрягать GC, чтобы этот мусор собрать. Поэтому JIT-компилятор научился магии под названием Escape Analysis (Анализ утечки). Как это работает? Допустим, у вас есть метод:

public int calculateArea(int x, int y) {
    // Создаем временный объект
    Point p = new Point(x, y); 
    return p.getX() * p.getY();
}
Казалось бы, при каждом вызове метода мы засоряем Heap новым объектом Point. Но JIT-компилятор во время работы программы анализирует код и задает себе вопрос: "А убегает ли этот объект за пределы метода?" В нашем случае p никуда не передается, не сохраняется в глобальную коллекцию и не возвращается наружу (возвращается только int). Объект не убегает (No Escape). ✨ Магия Скалярной замены (Scalar Replacement) Поняв это, JVM принимает гениальное решение: она вообще не создает объект Point в Куче! Вместо этого она "расщепляет" объект на его составляющие примитивы (поля x и y) и держит их в регистрах или других внутренних структурах JIT. Для процессора этот код превращается во что-то такое:

public int calculateArea(int x, int y) {
    int p_x = x;
    int p_y = y;
    return p_x * p_y;
}
Что это дает? 1. 0 байт выделено в Heap. 2. 0 миллисекунд потрачено на работу Garbage Collector. 3. Скорость выполнения может быть очень близка к нативной производительности. Итог: В большинстве обычных случаев можно не бояться создавать короткоживущие объекты внутри методов (DTO, обертки, Optional), если это делает код чище. JVM достаточно умна, чтобы "схлопнуть" их и не нагружать память. Экономить на спичках и переиспользовать один объект через reset() больше не нужно.

⌨️ Что такое static метод интерфейса? Статические методы интерфейса похожи на методы по умолчанию, за исключением того, что для них отсутствует возможность переопределения в классах, реализующих интерфейс. ✔️Статические методы в интерфейсе являются частью интерфейса без возможности переопределить их для объектов класса реализации; ✔️Методы класса java.lang.Object нельзя переопределить как статические; ✔️Статические методы в интерфейсе используются для обеспечения вспомогательных методов, например, проверки на null, сортировки коллекций и т.д. Вызывать static метод интерфейса можно используя имя интерфейса:

interface Paper {
    static void show() {
        System.out.println("static show()");
    }
}

class Licence {
    public void showPaper() {
        Paper.show();
    }
}

🔍 5 фишек Stream API, которые упростят код Stream API – мощный инструмент, но в нём есть интересные методы, о которых многие забывают. 🟢takeWhile() – берёт элементы, пока условие true. 🟢dropWhile() – пропускает элементы, пока условие true. 🟢iterate() – создаёт бесконечный поток. 🟢flatMap() – преобразует вложенные структуры в плоский поток. 🟢collect(Collectors.toMap()) – собирает Stream в Map. ✔️ Пример:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
numbers.stream()
       .takeWhile(n -> n < 4)
       .forEach(System.out::println); // 1, 2, 3
💡 Совет: Используйте эти методы, чтобы писать более лаконичный код без лишних for. #java #streamapi #functionalprogramming

⌨️ Дайте определение понятию «интерфейс». Какие модификаторы по умолчанию имеют поля и методы интерфейсов? Ключевое слово interface используется для создания полностью абстрактных классов. Основное предназначение интерфейса - определять каким образом мы можем использовать класс, который его реализует. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не реализует их поведение. Все методы неявно объявляются как public. Начиная с Java 8 в интерфейсах разрешается размещать реализацию методов по умолчанию default и статических static методов. Интерфейс также может содержать и поля. В этом случае они автоматически являются публичными public, статическими static и неизменяемыми final.

JVM-инженеры, общий сбор: 28 марта Яндекс проведет Я.Субботник по JVM-языкам Это митап для разработчиков, которые работают с
JVM-инженеры, общий сбор: 28 марта Яндекс проведет Я.Субботник по JVM-языкам Это митап для разработчиков, которые работают с языками Java Virtual Machine. Встреча пройдет в московском офисе Яндекса и в онлайн. Будем обсуждать новые подходы, делиться практическим опытом и нетворкать в неформальной обстановке. В программе — доклады про ускорение Java-фреймворков на примере Quarkus, устройство трассирующего профайлера (Qubership Profiler), реальные подводные камни java.time и оптимизация GraphQL API на базе GraphQL Java и Spring Framework. А еще круглые столы, активность от Яндекс Вертикалей и афтерпати. Подать заявку на митап можно здесь.