В чем разница между ArrayList и LinkedList? 🤓
Ответ:
ArrayList использует динамический массив, быстрый доступ по индексу (O(1)), но медленные вставки/удаления в середине (O(n)).
LinkedList использует двухсвязный список, быстрые вставки/удаления (O(1)), но медленный доступ по индексу (O(n)).
#собеседование
Ответ:
LinkedList использует двухсвязный список, быстрые вставки/удаления (O(1)), но медленный доступ по индексу (O(n)).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Структура и основные команды Liquibase
1. Файл конфигурации (liquibase.properties)
Файл liquibase.properties содержит настройки для подключения к БД и управления Liquibase.
Основные параметры:
Разбор параметров:
url – JDBC-URL базы данных (зависит от СУБД).
username и password – учетные данные для подключения.
driver – класс JDBC-драйвера (например, org.postgresql.Driver для PostgreSQL).
changeLogFile – путь к главному файлу changelog.
Где размещается?
В корне проекта (рядом с pom.xml/build.gradle).
Или указывается явно при запуске:
2. Основные команды CLI
Liquibase предоставляет консольные команды для управления миграциями.
update – применение изменений
Применяет все невыполненные changeSet’ы из changelog.
Что происходит?
Liquibase проверяет таблицу DATABASECHANGELOG.
Находит changeSet’ы, которых нет в этой таблице.
Применяет их в порядке указания в changelog.
rollback – откат изменений
Возвращает БД к предыдущему состоянию.
status – проверка состояния БД
Показывает, какие changeSet’ы не применены.
Вывод:
validate – проверка корректности changelog
Проверяет синтаксис changelog без применения изменений.
Если есть ошибки, выведет сообщение, например:
3. Жизненный цикл изменений
Как Liquibase применяет changeSet’ы?
Парсинг changelog:
Liquibase читает главный файл (например, db.changelog-master.xml).
Загружает все вложенные changeSet’ы.
Проверка DATABASECHANGELOG:
Сравнивает список changeSet’ов с теми, что уже выполнены (хранятся в таблице DATABASECHANGELOG).
Применение изменений:
Невыполненные changeSet’ы применяются в порядке их объявления.
После успешного выполнения информация о changeSet’е записывается в DATABASECHANGELOG.
Контроль версий и порядок выполнения
Уникальность changeSet’а определяется по:
id (например, "1").
author (например, "alex").
Путь к файлу changelog.
Порядок выполнения:
Liquibase выполнит 001-create-users.xml раньше, чем 002-add-email.xml.
Атрибуты, влияющие на выполнение:
runOnChange="true" – повторно выполнит changeSet, если его содержимое изменилось.
failOnError="false" – пропустит ошибку (например, если таблица уже существует).
#Java #middle #Liquibase
1. Файл конфигурации (liquibase.properties)
Файл liquibase.properties содержит настройки для подключения к БД и управления Liquibase.
Основные параметры:
# Подключение к БД
url=jdbc:postgresql://localhost:5432/mydb
username=user
password=pass
driver=org.postgresql.Driver
# Настройки changelog
changeLogFile=db/changelog/db.changelog-master.xml
# Дополнительные параметры
liquibase.hub.mode=off # Отключение Liquibase Hub (если не используется)
Разбор параметров:
url – JDBC-URL базы данных (зависит от СУБД).
username и password – учетные данные для подключения.
driver – класс JDBC-драйвера (например, org.postgresql.Driver для PostgreSQL).
changeLogFile – путь к главному файлу changelog.
Где размещается?
В корне проекта (рядом с pom.xml/build.gradle).
Или указывается явно при запуске:
liquibase --defaults-file=config/liquibase.properties update
2. Основные команды CLI
Liquibase предоставляет консольные команды для управления миграциями.
update – применение изменений
Применяет все невыполненные changeSet’ы из changelog.
liquibase update
Что происходит?
Liquibase проверяет таблицу DATABASECHANGELOG.
Находит changeSet’ы, которых нет в этой таблице.
Применяет их в порядке указания в changelog.
rollback – откат изменений
Возвращает БД к предыдущему состоянию.
# Откат до тега v1.0
liquibase rollback v1.0
# Откат последнего changeSet’а
liquibase rollbackCount 1
# Откат до определенной даты
liquibase rollbackToDate 2024-01-01
status – проверка состояния БД
Показывает, какие changeSet’ы не применены.
liquibase status
Вывод:
2 changesets have not been applied to mydb@jdbc:postgresql://localhost:5432/mydb
validate – проверка корректности changelog
Проверяет синтаксис changelog без применения изменений.
liquibase validate
Если есть ошибки, выведет сообщение, например:
ERROR: ChangeSet db/changelog/changes/001-create-table.xml::1::alex failed. Reason: Table 'users' already exists
3. Жизненный цикл изменений
Как Liquibase применяет changeSet’ы?
Парсинг changelog:
Liquibase читает главный файл (например, db.changelog-master.xml).
Загружает все вложенные changeSet’ы.
Проверка DATABASECHANGELOG:
Сравнивает список changeSet’ов с теми, что уже выполнены (хранятся в таблице DATABASECHANGELOG).
Применение изменений:
Невыполненные changeSet’ы применяются в порядке их объявления.
После успешного выполнения информация о changeSet’е записывается в DATABASECHANGELOG.
Контроль версий и порядок выполнения
Уникальность changeSet’а определяется по:
id (например, "1").
author (например, "alex").
Путь к файлу changelog.
Порядок выполнения:
<databaseChangeLog>
<include file="db/changelog/changes/001-create-users.xml"/>
<include file="db/changelog/changes/002-add-email.xml"/>
</databaseChangeLog>
Liquibase выполнит 001-create-users.xml раньше, чем 002-add-email.xml.
Атрибуты, влияющие на выполнение:
runOnChange="true" – повторно выполнит changeSet, если его содержимое изменилось.
failOnError="false" – пропустит ошибку (например, если таблица уже существует).
#Java #middle #Liquibase
Что выведет код?
#Tasks
public class Task290525 {
public static void main(String[] args) {
System.out.println(1.0 / 0.0);
}
}
#Tasks
Чем отличается HashSet от TreeSet? 🤓
Ответ:
HashSet хранит элементы в хэш-таблице, не упорядочивает их, но работает быстрее (O(1) для добавления/поиска).
TreeSet хранит элементы в
отсортированном виде (на основе красно-черного дерева), но операции медленнее (O(log n)).
#собеседование
Ответ:
TreeSet хранит элементы в
отсортированном виде (на основе красно-черного дерева), но операции медленнее (O(log n)).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Глубокое изучение типа данных char в Java
Тип char в Java — это единственный примитивный тип, предназначенный для хранения символов. Однако под «символом» в контексте Java подразумевается не просто буква или цифра, а 16-битное значение, соответствующее одному коду Unicode. Это делает char более универсальным, чем аналогичные типы в других языках (например, char в C/C++ — это просто байт).
Тем не менее, с учетом особенностей кодировки Unicode, поведения в выражениях и сравнении с другими примитивами, char — не такой уж простой тип.
Что представляет собой char
В Java char — это целое беззнаковое значение, хранящееся в 16 битах (2 байта). Диапазон значений — от 0 до 65 535. Это соответствует возможным значениям Unicode Code Units, используемым для представления символов в кодировке UTF-16.
В отличие от byte, short, int и других числовых типов, char:
Не поддерживает отрицательные значения.
Не используется в арифметике напрямую (но может быть преобразован в int).
Представляет не число, а код символа, хотя технически это просто целое значение.
Хранение в памяти
Как и все примитивные типы, char хранится в стеке, если используется как локальная переменная, и в куче — если является полем объекта. В обоих случаях он занимает ровно 2 байта (16 бит).
Символ и кодировка Unicode
Java изначально проектировалась с поддержкой международного текста, поэтому char хранит значение по спецификации Unicode. Однако важно понимать: char хранит одну кодовую единицу UTF-16, а не обязательно один графический символ.
Некоторые символы Unicode (например, эмодзи или древние алфавиты) имеют коды за пределами 16 бит. Такие символы представлены в UTF-16 двумя char, известными как суррогатная пара.
Это значит, что один char — это не всегда "один символ", что может привести к ошибкам при разборе строк, итерации по символам или определении длины строки.
Пример:
Экранирование символов
Литералы char записываются в одиночных кавычках:
Java поддерживает экранированные символы, например:
'\n' — перевод строки
'\t' — табуляция
'\'' — апостроф
'\\' — обратный слеш
'\u0041' — Unicode-последовательность (в данном случае это символ 'A')
Unicode-последовательности (\uXXXX) можно использовать даже в имени переменной или в коде, до начала компиляции — они обрабатываются на уровне лексического анализатора, еще до построения синтаксического дерева.
#Java #для_новичков #beginner #char
Тип char в Java — это единственный примитивный тип, предназначенный для хранения символов. Однако под «символом» в контексте Java подразумевается не просто буква или цифра, а 16-битное значение, соответствующее одному коду Unicode. Это делает char более универсальным, чем аналогичные типы в других языках (например, char в C/C++ — это просто байт).
Тем не менее, с учетом особенностей кодировки Unicode, поведения в выражениях и сравнении с другими примитивами, char — не такой уж простой тип.
Что представляет собой char
В Java char — это целое беззнаковое значение, хранящееся в 16 битах (2 байта). Диапазон значений — от 0 до 65 535. Это соответствует возможным значениям Unicode Code Units, используемым для представления символов в кодировке UTF-16.
В отличие от byte, short, int и других числовых типов, char:
Не поддерживает отрицательные значения.
Не используется в арифметике напрямую (но может быть преобразован в int).
Представляет не число, а код символа, хотя технически это просто целое значение.
Хранение в памяти
Как и все примитивные типы, char хранится в стеке, если используется как локальная переменная, и в куче — если является полем объекта. В обоих случаях он занимает ровно 2 байта (16 бит).
Символ и кодировка Unicode
Java изначально проектировалась с поддержкой международного текста, поэтому char хранит значение по спецификации Unicode. Однако важно понимать: char хранит одну кодовую единицу UTF-16, а не обязательно один графический символ.
Некоторые символы Unicode (например, эмодзи или древние алфавиты) имеют коды за пределами 16 бит. Такие символы представлены в UTF-16 двумя char, известными как суррогатная пара.
Это значит, что один char — это не всегда "один символ", что может привести к ошибкам при разборе строк, итерации по символам или определении длины строки.
Пример:
String s = "😀";
System.out.println(s.length()); // 2, а не 1
Здесь length() возвращает 2, потому что символ представлен двумя char.
Экранирование символов
Литералы char записываются в одиночных кавычках:
char c = 'A';
Java поддерживает экранированные символы, например:
'\n' — перевод строки
'\t' — табуляция
'\'' — апостроф
'\\' — обратный слеш
'\u0041' — Unicode-последовательность (в данном случае это символ 'A')
Unicode-последовательности (\uXXXX) можно использовать даже в имени переменной или в коде, до начала компиляции — они обрабатываются на уровне лексического анализатора, еще до построения синтаксического дерева.
#Java #для_новичков #beginner #char
Поведение в выражениях и преобразования
Несмотря на то, что char — это не числовой тип, он может участвовать в арифметике. В любых выражениях с участием char он неявно преобразуется в int.
Но обратное требует явного приведения:
Сравнение с другими примитивными типами
В отличие от byte, short, int, char — беззнаковый.
Он занимает 2 байта, как short, но short — знаковый (-32 768 до 32 767), а char — 0 до 65 535.
В арифметике char ведет себя как int, автоматически повышая тип.
В отличие от String, char представляет одну кодовую единицу, а не последовательность символов.
В отличие от boolean, char может участвовать в арифметических выражениях и преобразованиях.
Инициализация и значения по умолчанию
Локальные переменные char должны быть явно инициализированы.
Поля классов по умолчанию получают значение \u0000, что соответствует нулевому символу Unicode (не отображается в консоли).
Частые ошибки и подводные камни
Суррогатные пары. При работе со строками, содержащими символы за пределами BMP (Basic Multilingual Plane), важно использовать методы вроде codePointAt() и Character.toChars(), чтобы не потерять часть символа.
Арифметика с char. Все выражения приводятся к int, что может привести к неожиданному переполнению или необходимости явного приведения.
Сравнение символов. Операции c1 < c2 работают корректно, но сравниваются числовые значения Unicode, а не "лексикографическое положение" в каком-либо языке.
Обработка управляющих символов. Символы вроде '\0', '\n', '\r' видны в коде, но не обязательно видны в выводе — их эффект зависит от среды (консоль, IDE, файл и т.д.).
#Java #для_новичков #beginner #char
Несмотря на то, что char — это не числовой тип, он может участвовать в арифметике. В любых выражениях с участием char он неявно преобразуется в int.
char c = 'A';
int x = c + 1; // x == 66
Но обратное требует явного приведения:
char next = (char)(c + 1); // 'B'
Аналогично, попытка присвоить результат арифметики напрямую переменной типа char вызовет ошибку компиляции без приведения.
Сравнение с другими примитивными типами
В отличие от byte, short, int, char — беззнаковый.
Он занимает 2 байта, как short, но short — знаковый (-32 768 до 32 767), а char — 0 до 65 535.
В арифметике char ведет себя как int, автоматически повышая тип.
В отличие от String, char представляет одну кодовую единицу, а не последовательность символов.
В отличие от boolean, char может участвовать в арифметических выражениях и преобразованиях.
Инициализация и значения по умолчанию
Локальные переменные char должны быть явно инициализированы.
Поля классов по умолчанию получают значение \u0000, что соответствует нулевому символу Unicode (не отображается в консоли).
Частые ошибки и подводные камни
Суррогатные пары. При работе со строками, содержащими символы за пределами BMP (Basic Multilingual Plane), важно использовать методы вроде codePointAt() и Character.toChars(), чтобы не потерять часть символа.
Арифметика с char. Все выражения приводятся к int, что может привести к неожиданному переполнению или необходимости явного приведения.
Сравнение символов. Операции c1 < c2 работают корректно, но сравниваются числовые значения Unicode, а не "лексикографическое положение" в каком-либо языке.
Обработка управляющих символов. Символы вроде '\0', '\n', '\r' видны в коде, но не обязательно видны в выводе — их эффект зависит от среды (консоль, IDE, файл и т.д.).
#Java #для_новичков #beginner #char
Что выведет код?
#Tasks
public class Task300525 {
public static void main(String[] args) {
char c = 'A';
c += 1.5;
System.out.println(c);
}
}
#Tasks
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того что предлагали на прошлой неделе и что проигрывает в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того что предлагали на прошлой неделе и что проигрывает в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
В чем разница между throw и throws? 🤓
Ответ:
throw используется для явного выброса исключения, например: throw new IOException();.
throws указывается в сигнатуре метода, чтобы сообщить, какие проверяемые исключения он может выбросить, например: void method() throws IOException.
#собеседование
Ответ:
throws указывается в сигнатуре метода, чтобы сообщить, какие проверяемые исключения он может выбросить, например: void method() throws IOException.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
С 24.05 по 31.05
Предыдущий пост(с 17.05 по 23.05)
Следующая неделя
Воскресный мотивационный пост:
"Твой первый проект — важнее, чем думаешь"
Выбранная голосованием тема:
Паттерны проектирования на Java: суть, история и применение
Запись встреч:
Изучаем Swagger
Обучающие статьи:
Глубокое изучение типа данных double в Java
Глубокое изучение типа float в Java
Глубокое изучение типа данных char в Java
Введение в Liquibase
Структура и основные команды Liquibase
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!🥳
Авторские статьи:
Как я память искал (Часть I)
Как я память искал (Часть II)
Полезные статьи и видео:
Управление транзакциями в Spring: подробно о @Transactional
Делаем свою простейшую систему сборки для Java
Проблема N+1 в Hibernate — ВСЕ СПОСОБЫ решения
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 17.05 по 23.05)
Следующая неделя
Воскресный мотивационный пост:
"Твой первый проект — важнее, чем думаешь"
Выбранная голосованием тема:
Паттерны проектирования на Java: суть, история и применение
Запись встреч:
Изучаем Swagger
Обучающие статьи:
Глубокое изучение типа данных double в Java
Глубокое изучение типа float в Java
Глубокое изучение типа данных char в Java
Введение в Liquibase
Структура и основные команды Liquibase
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!
Авторские статьи:
Как я память искал (Часть I)
Как я память искал (Часть II)
Полезные статьи и видео:
Управление транзакциями в Spring: подробно о @Transactional
Делаем свою простейшую систему сборки для Java
Проблема N+1 в Hibernate — ВСЕ СПОСОБЫ решения
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Please open Telegram to view this post
VIEW IN TELEGRAM
Распространённые ошибки
1. Логика в контроллерах
Признак: контроллер становится "сервисом", содержащим условия, циклы, доступ к БД. Это нарушает принципы чистой архитектуры и усложняет тестирование.
2. Использование Entity в представлении
Передача @Entity напрямую в шаблон может привести к:
Утечке данных (например, паролей).
Ошибкам LazyInitializationException.
Сильной связанности представления с базой данных.
Решение: использовать DTO или ViewModel.
3. Жёсткая связность между слоями
View не должно зависеть от Repository, а Controller — от Entity. Каждый слой должен взаимодействовать только с соседним.
4. Отсутствие DTO
Использование одной и той же модели во всех сценариях ведёт к путанице и проблемам безопасности. Лучше использовать отдельные классы:
UserCreateRequest
UserResponse
UserUpdateRequest
Рекомендации по проектированию
Структура проекта
Хорошей практикой является разделение кода по слоям:
URL-дизайн
Соблюдайте RESTful-стиль:
GET /users — получить список пользователей.
GET /users/{id} — получить конкретного пользователя.
POST /users — создать.
PUT /users/{id} — обновить.
DELETE /users/{id} — удалить.
Использование DTO
Расширения и адаптации MVC
SPA + API
При использовании Vue, React или Angular, представление полностью переносится на фронтенд. В этом случае Spring работает как REST API с @RestController, и классическая схема MVC трансформируется в «REST + JSON».
Поддержка реактивности
Spring WebFlux реализует неблокирующую модель с Mono и Flux, сохраняя при этом логическую структуру MVC. Подходит для высоконагруженных и асинхронных приложений.
Тестирование компонентов MVC
Контроллеры — @WebMvcTest, MockMvc.
Сервисы — @SpringBootTest или с моками (@MockBean).
Репозитории — @DataJpaTest.
#Java #для_новичков #beginner #on_request #mvc
1. Логика в контроллерах
Признак: контроллер становится "сервисом", содержащим условия, циклы, доступ к БД. Это нарушает принципы чистой архитектуры и усложняет тестирование.
2. Использование Entity в представлении
Передача @Entity напрямую в шаблон может привести к:
Утечке данных (например, паролей).
Ошибкам LazyInitializationException.
Сильной связанности представления с базой данных.
Решение: использовать DTO или ViewModel.
3. Жёсткая связность между слоями
View не должно зависеть от Repository, а Controller — от Entity. Каждый слой должен взаимодействовать только с соседним.
4. Отсутствие DTO
Использование одной и той же модели во всех сценариях ведёт к путанице и проблемам безопасности. Лучше использовать отдельные классы:
UserCreateRequest
UserResponse
UserUpdateRequest
Рекомендации по проектированию
Структура проекта
Хорошей практикой является разделение кода по слоям:
com.example.myapp
├── controller
├── service
│ └── impl
├── repository
├── dto
├── model
├── config
URL-дизайн
Соблюдайте RESTful-стиль:
GET /users — получить список пользователей.
GET /users/{id} — получить конкретного пользователя.
POST /users — создать.
PUT /users/{id} — обновить.
DELETE /users/{id} — удалить.
Использование DTO
public class UserResponse {
private Long id;
private String name;
}
public class UserCreateRequest {
private String name;
private String email;
}
Расширения и адаптации MVC
SPA + API
При использовании Vue, React или Angular, представление полностью переносится на фронтенд. В этом случае Spring работает как REST API с @RestController, и классическая схема MVC трансформируется в «REST + JSON».
Поддержка реактивности
Spring WebFlux реализует неблокирующую модель с Mono и Flux, сохраняя при этом логическую структуру MVC. Подходит для высоконагруженных и асинхронных приложений.
Тестирование компонентов MVC
Контроллеры — @WebMvcTest, MockMvc.
Сервисы — @SpringBootTest или с моками (@MockBean).
Репозитории — @DataJpaTest.
#Java #для_новичков #beginner #on_request #mvc
Please open Telegram to view this post
VIEW IN TELEGRAM
Есть предложение встретиться завтра в 16:00 по МСК на лайвкодинг!
Тема будет: Многопоточка на примерах
Тема будет: Многопоточка на примерах
Anonymous Poll
33%
О, интересно, я приду ✈️
27%
Блииин, я хочу, но нет возможности 🤷♀️
39%
Посмотрю в записи 👌
0%
Не приду. Фигню какую то рассматриваете 🤢