Нужно переименовать пять переменных одновременно? Или добавить .orElseThrow() к каждому Optional в цепочке? Обычно копируешь первую строчку, вставляешь, правишь, повторяешь еще четыре раза.
Скучно, медленно, и легко ошибиться. А можно умнее.
🔹 Что делает
— Создает несколько курсоров в разных местах кода одновременно
— Все изменения применяются параллельно: печатаешь один раз → меняется везде
— Работает с выделением: можно выделить несколько фрагментов и редактировать их синхронно
— Понимает контекст: может выбрать все вхождения переменной или строки в файле
🔹 Зачем это нужно
— Массовые однотипные правки за секунды вместо копипасты
— Видишь все изменения сразу, до применения
— Идеально для инициализации билдеров: добавляешь .with перед каждым полем одним движением
— Работает с вертикальными блоками кода: легко править список параметров или цепочку вызовов
🔹 Как использовать
— Способ 1: Alt+J (Windows/Linux) или ⌃+G (macOS) — выделяет следующее вхождение слова под курсором.
Нажимайте повторно, чтобы добавить еще вхождения, или Ctrl+Alt+Shift+J / ⌃+⌘+G для всех сразу
— Способ 2: Alt+Shift+Click (Windows/Linux) или ⌥+Shift+Click (macOS) — ставит курсор в место клика.
Кликайте в нужные места, создавая множество курсоров вручную
— Способ 3: Alt+Shift+Insert (Windows/Linux) или ⌘+Shift+8 (macOS) — Column Selection Mode для вертикального выделения.
Для отмены всех курсоров кроме основного: Esc
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤5👍4
🚀 В IT ценится не перфекционизм, а движение вперёд, и если вы давно откладывали обучение — самое время начать.
❤️ Proglib Academy продлевает розыгрыш MacBook Pro 14 до 30 ноября!
Что нужно:
⚡️ выбрать курс;
⚡️ пройти минимум две недели обучения (можно за два вечера);
⚡️ написать куратору #розыгрыш;
⚡️ забрать макбук.
🎓 Курсы, которые участвуют
👉 Участвовать
❤️ Proglib Academy продлевает розыгрыш MacBook Pro 14 до 30 ноября!
Что нужно:
⚡️ выбрать курс;
⚡️ пройти минимум две недели обучения (можно за два вечера);
⚡️ написать куратору #розыгрыш;
⚡️ забрать макбук.
🎓 Курсы, которые участвуют
👉 Участвовать
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28👍3💯2
Как вы обычно обновляете одно поле в неизменяемом объекте? Создаёте копию с нужным значением?
Муторно. Lombok умеет делать это просто и элегантно.
🔹 Аннотация @With
Генерирует методы withX(...), которые создают копию объекта с изменённым полем. Подходит для immutable-моделей и паттерна builder. Класс при этом должен быть final (например, через @Value или вручную).
🔹 Пример
@Value
@With
public class User {
String name;
int age;
}
Теперь можно:
User user1 = new User("Alice", 25);
User user2 = user1.withAge(30); // создаётся новый объект с новым ageОбъекты остаются неизменяемыми, но при этом легко "обновляемыми".
🔹 Зачем это нужно
— Удобно при работе с immutable-классами.
— Простой способ "копировать с изменением".
— Чистый, декларативный стиль без boilerplate.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤4🔥3🥱1
🎯 Record Patterns в Java 21: как компилятор превращает деструктуризацию в bytecode
После двух preview (Java 19-20), Record Patterns стали финальной фичей в Java 21. Разберем механику работы под капотом.
🔹 Что такое Record Patterns
Это расширение pattern matching для деструктуризации record классов:
🔹 Nested patterns — вложенная деструктуризация
Мощь раскрывается с вложенными record'ами:
Компилятор генерирует код примерно так:
Для вложенных patterns компилятор создает каскад instanceof проверок и вызовов accessor методов.
🔹 Pattern Matching для switch
Record patterns работают в switch (JEP 441 - тоже финализирован в Java 21):
🔹 Guarded patterns
Можно добавлять условия:
🔹 Важное изменение с preview
В финальной версии убрали поддержку record patterns в enhanced for:
Причина: семантическая неоднозначность и возможные проблемы с нулевыми элементами.
📌 Record Patterns + Pattern Matching for switch — это огромный шаг к функциональному стилю в Java. Код становится декларативным, компактным и безопасным.
🐸 Библиотека джависта
#CoreJava
После двух preview (Java 19-20), Record Patterns стали финальной фичей в Java 21. Разберем механику работы под капотом.
🔹 Что такое Record Patterns
Это расширение pattern matching для деструктуризации record классов:
record Point(int x, int y) {}
// До Java 21
if (obj instanceof Point point) {
int x = point.x();
int y = point.y();
// use x, y
}
// Java 21
if (obj instanceof Point(int x, int y)) {
// x и y автоматически в scope
System.out.println(x + y);
}
🔹 Nested patterns — вложенная деструктуризация
Мощь раскрывается с вложенными record'ами:
record Point(int x, int y) {}
record Rectangle(Point upperLeft, Point lowerRight) {}
// Одна строка вместо цепочки вызовов
if (shape instanceof Rectangle(Point(int x1, int y1),
Point(int x2, int y2))) {
int area = Math.abs((x2-x1) * (y2-y1));
}
Компилятор генерирует код примерно так:
// Исходный код
if (obj instanceof Point(int x, int y)) {
process(x, y);
}
// Что генерирует компилятор (упрощенно)
if (obj instanceof Point __temp) {
int x = __temp.x();
int y = __temp.y();
process(x, y);
}
Для вложенных patterns компилятор создает каскад instanceof проверок и вызовов accessor методов.
🔹 Pattern Matching для switch
Record patterns работают в switch (JEP 441 - тоже финализирован в Java 21):
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double a, double b, double c) implements Shape {}
double area(Shape shape) {
return switch(shape) {
case Circle(double r) -> Math.PI * r * r;
case Rectangle(double w, double h) -> w * h;
case Triangle(double a, double b, double c) -> {
double s = (a + b + c) / 2;
yield Math.sqrt(s * (s-a) * (s-b) * (s-c));
}
};
}
🔹 Guarded patterns
Можно добавлять условия:
String classify(Object obj) {
return switch(obj) {
case Point(int x, int y) when x == y -> "diagonal";
case Point(int x, int y) when x > y -> "above diagonal";
case Point(int x, int y) -> "below diagonal";
default -> "not a point";
};
}
🔹 Важное изменение с preview
В финальной версии убрали поддержку record patterns в enhanced for:
// Работало в preview
for (Point(int x, int y) : points) { }
// Больше не работает в Java 21 final
Причина: семантическая неоднозначность и возможные проблемы с нулевыми элементами.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤2👍2👏2
🔥 Как настроить Liquibase для управления миграциями БД
Liquibase — это инструмент для версионирования схемы базы данных. Забудьте про ручные SQL-скрипты и проблемы с синхронизацией между окружениями.
Работает декларативно, отслеживает все изменения, поддерживает rollback и работает с любыми реляционными БД.
1️⃣ Добавляем зависимости
Нужна одна основная зависимость: liquibase-core. Если используете Spring Boot, добавьте spring-boot-starter-liquibase — он автоматически интегрируется с DataSource и запускается при старте приложения.
Критически важно добавить JDBC-драйвер вашей БД (postgresql, mysql-connector и т.д.). Без него Liquibase не сможет подключиться и применить миграции.
2️⃣ Создаём структуру changelog-файлов
Создайте директорию resources/db/changelog/. В корне положите главный файл db.changelog-master.yaml — это точка входа, которая включает все остальные миграции.
В мастер-файле перечисляете пути к конкретным changeset-файлам в порядке применения. Называйте файлы по схеме: v1.0-create-users-table.yaml, v1.1-add-email-column.yaml — так проще ориентироваться в истории изменений.
3️⃣ Настраиваем application.yml
В конфигурации укажите путь к мастер-файлу через параметр spring.liquibase.change-log. По умолчанию это classpath:db/changelog/db.changelog-master.yaml.
Обязательно настройте параметры enabled (включить/выключить), drop-first (очистка БД перед стартом — только для dev!) и contexts (для разделения миграций по окружениям: dev, test, prod).
4️⃣ Пишем changeset'ы
Каждое изменение оборачивается в changeset с уникальным id и автором. Liquibase отслеживает, какие changeset'ы уже применены через служебную таблицу databasechangelog.
Основные типы изменений:
▪️ createTable / dropTable — создание/удаление таблиц
▪️ addColumn / dropColumn — добавление/удаление колонок
▪️ createIndex — создание индексов для оптимизации запросов
▪️ addForeignKey — настройка связей между таблицами
▪️ insert / update — заполнение справочников и тестовых данных
▪️ sql / sqlFile — для сложных кастомных запросов
Используйте preconditions для проверки условий перед применением: например, не создавать таблицу, если она уже существует.
5️⃣ Настраиваем rollback
Liquibase умеет откатывать изменения. Для большинства операций rollback генерируется автоматически, но для sql и sqlFile нужно явно указывать rollback-блок.
Добавляйте тег rollback с SQL-командами отката. Для createTable это будет dropTable, для addColumn — dropColumn. Это критически важно для production — без rollback вы не сможете откатить проблемную миграцию.
6️⃣ Работа с разными окружениями
Используйте contexts и labels для разделения миграций. Тестовые данные помечайте context="dev", production-миграции — context="prod". При запуске приложения указывайте нужный context в конфигурации.
Можно создать отдельные файлы для каждого окружения: db.changelog-dev.yaml с тестовыми данными и db.changelog-prod.yaml только со структурными изменениями. Подключайте их условно через профили Spring.
7️⃣ Лучшие практики
▪️ Никогда не изменяйте уже применённые changeset'ы — создавайте новые для исправлений
▪️ Один changeset = одно атомарное изменение. Не пихайте всё в один файл
▪️ Используйте runOnChange="false" чтобы changeset применялся только один раз
▪️ Добавляйте failOnError="true" для критичных миграций
▪️ Тестируйте миграции на копии production БД перед деплоем
✔️ Что происходит под капотом
При старте приложения Liquibase подключается к БД и проверяет наличие служебных таблиц DATABASECHANGELOG и DATABASECHANGELOGLOCK. Если их нет — создаёт.
Затем читает master-файл, получает список всех changeset'ов и сверяет с таблицей DATABASECHANGELOG. Новые changeset'ы применяются последовательно, информация о них записывается в таблицу с MD5-хэшем для контроля целостности.
💡 Бонус-совет
Интегрируйте Liquibase с CI/CD. Перед деплоем запускайте команду liquibase validate для проверки корректности changelog'ов. В pipeline добавьте команду liquibase updateSQL чтобы увидеть, какой SQL будет выполнен, без реального применения.
🐸 Библиотека джависта
#Enterprise
Liquibase — это инструмент для версионирования схемы базы данных. Забудьте про ручные SQL-скрипты и проблемы с синхронизацией между окружениями.
Работает декларативно, отслеживает все изменения, поддерживает rollback и работает с любыми реляционными БД.
Нужна одна основная зависимость: liquibase-core. Если используете Spring Boot, добавьте spring-boot-starter-liquibase — он автоматически интегрируется с DataSource и запускается при старте приложения.
Критически важно добавить JDBC-драйвер вашей БД (postgresql, mysql-connector и т.д.). Без него Liquibase не сможет подключиться и применить миграции.
Создайте директорию resources/db/changelog/. В корне положите главный файл db.changelog-master.yaml — это точка входа, которая включает все остальные миграции.
В мастер-файле перечисляете пути к конкретным changeset-файлам в порядке применения. Называйте файлы по схеме: v1.0-create-users-table.yaml, v1.1-add-email-column.yaml — так проще ориентироваться в истории изменений.
В конфигурации укажите путь к мастер-файлу через параметр spring.liquibase.change-log. По умолчанию это classpath:db/changelog/db.changelog-master.yaml.
Обязательно настройте параметры enabled (включить/выключить), drop-first (очистка БД перед стартом — только для dev!) и contexts (для разделения миграций по окружениям: dev, test, prod).
Каждое изменение оборачивается в changeset с уникальным id и автором. Liquibase отслеживает, какие changeset'ы уже применены через служебную таблицу databasechangelog.
Основные типы изменений:
▪️ createTable / dropTable — создание/удаление таблиц
▪️ addColumn / dropColumn — добавление/удаление колонок
▪️ createIndex — создание индексов для оптимизации запросов
▪️ addForeignKey — настройка связей между таблицами
▪️ insert / update — заполнение справочников и тестовых данных
▪️ sql / sqlFile — для сложных кастомных запросов
Используйте preconditions для проверки условий перед применением: например, не создавать таблицу, если она уже существует.
Liquibase умеет откатывать изменения. Для большинства операций rollback генерируется автоматически, но для sql и sqlFile нужно явно указывать rollback-блок.
Добавляйте тег rollback с SQL-командами отката. Для createTable это будет dropTable, для addColumn — dropColumn. Это критически важно для production — без rollback вы не сможете откатить проблемную миграцию.
Используйте contexts и labels для разделения миграций. Тестовые данные помечайте context="dev", production-миграции — context="prod". При запуске приложения указывайте нужный context в конфигурации.
Можно создать отдельные файлы для каждого окружения: db.changelog-dev.yaml с тестовыми данными и db.changelog-prod.yaml только со структурными изменениями. Подключайте их условно через профили Spring.
▪️ Никогда не изменяйте уже применённые changeset'ы — создавайте новые для исправлений
▪️ Один changeset = одно атомарное изменение. Не пихайте всё в один файл
▪️ Используйте runOnChange="false" чтобы changeset применялся только один раз
▪️ Добавляйте failOnError="true" для критичных миграций
▪️ Тестируйте миграции на копии production БД перед деплоем
При старте приложения Liquibase подключается к БД и проверяет наличие служебных таблиц DATABASECHANGELOG и DATABASECHANGELOGLOCK. Если их нет — создаёт.
Затем читает master-файл, получает список всех changeset'ов и сверяет с таблицей DATABASECHANGELOG. Новые changeset'ы применяются последовательно, информация о них записывается в таблицу с MD5-хэшем для контроля целостности.
Интегрируйте Liquibase с CI/CD. Перед деплоем запускайте команду liquibase validate для проверки корректности changelog'ов. В pipeline добавьте команду liquibase updateSQL чтобы увидеть, какой SQL будет выполнен, без реального применения.
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🔥1
🎓 Экспресс-курс «Математика для Data Science» стартует 4 декабря
Этот курс для вас, если вы:
🧑💻 Программист
Когда нужно понять, что происходит «под капотом» ML-алгоритмов.
📊 Начинающий DS / аналитик / студент
Чтобы закрыть теорию, подтянуть фундамент и собрать портфолио.
📈 Смежный специалист
Чтобы уверенно работать с моделями, статистикой и гипотезами.
🎁 Сейчас лучший момент стартовать:
— скидка 40% на курс до конца ноября
— можно пройти бесплатный тест на знание основ математики
👉 Записаться на курс
Этот курс для вас, если вы:
🧑💻 Программист
Когда нужно понять, что происходит «под капотом» ML-алгоритмов.
📊 Начинающий DS / аналитик / студент
Чтобы закрыть теорию, подтянуть фундамент и собрать портфолио.
📈 Смежный специалист
Чтобы уверенно работать с моделями, статистикой и гипотезами.
🎁 Сейчас лучший момент стартовать:
— скидка 40% на курс до конца ноября
— можно пройти бесплатный тест на знание основ математики
👉 Записаться на курс
Forwarded from Библиотека задач по Java | тесты, код, задания
Что будет результатом фрагмента кода?
Anonymous Quiz
31%
1 2 3 4 5
25%
4 5
25%
Ничего
14%
Ошибка компиляции
6%
Посмотреть ответ
👍8🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14👍1🔥1💯1👾1
This media is not supported in your browser
VIEW IN TELEGRAM
Чем важна математика расскажет Мария Тихонова - кандидат компьютерных наук, руководитель исследовательского направления SberAI, доцент факультета компьютерных наук и преподаватель НИУ ВШЭ на курсе «Математика для Data Science» от Proglib Academy.
Курс предусматривает выполнение практического проекта с фидбеком от экспертов. За проект можно взять темы:
• обучите градиентный спуск для предсказания цен на квартиры
• создадите классификатор тональности или тематики текста
• построите простую рекомендательную систему на матричных разложениях
Бонусы:
- скидка 40% до 30 ноября
- если оплатить до конца ноября, получите курс «Базовая математика» в подарок
➡️ Пройти бесплатный тест на знание математики
Записаться на курс
Please open Telegram to view this post
VIEW IN TELEGRAM