🤔 Назови основные свойства транзакции
В базах данных и многопоточных системах транзакция — это атомарная последовательность операций, которая должна выполняться корректно и полностью.
🚩Атомарность (Atomicity) — "всё или ничего"
Транзакция выполняется полностью или не выполняется вовсе.
Перевод 1000 рублей с одного счёта на другой:
- Списать 1000 рублей с А
- Зачислить 1000 рублей на B
Если вторая операция не удалась, первая должна быть отменена.
🚩Согласованность (Consistency) — "данные остаются корректными"
После транзакции данные должны оставаться в логически правильном состоянии.
🚩Изолированность (Isolation) — "отдельно от других транзакций"
Одна транзакция не должна мешать выполнению другой.
Два клиента одновременно бронируют одно и то же место в самолёте.
Система должна обработать их по очереди, а не одновременно.
В Java изолированность регулируется уровнями транзакций (
🚩Долговечность (Durability) — "данные не теряются"
После успешного завершения транзакции данные не должны теряться даже при сбоях (например, отключении электричества).
Ставь 👍 и забирай 📚 Базу знаний
В базах данных и многопоточных системах транзакция — это атомарная последовательность операций, которая должна выполняться корректно и полностью.
🚩Атомарность (Atomicity) — "всё или ничего"
Транзакция выполняется полностью или не выполняется вовсе.
Перевод 1000 рублей с одного счёта на другой:
- Списать 1000 рублей с А
- Зачислить 1000 рублей на B
Если вторая операция не удалась, первая должна быть отменена.
try {
connection.setAutoCommit(false); // Отключаем автокоммит
withdraw(accountA, 1000);
deposit(accountB, 1000);
connection.commit(); // Подтверждаем транзакцию
} catch (Exception e) {
connection.rollback(); // Откат в случае ошибки
}🚩Согласованность (Consistency) — "данные остаются корректными"
После транзакции данные должны оставаться в логически правильном состоянии.
🚩Изолированность (Isolation) — "отдельно от других транзакций"
Одна транзакция не должна мешать выполнению другой.
Два клиента одновременно бронируют одно и то же место в самолёте.
Система должна обработать их по очереди, а не одновременно.
В Java изолированность регулируется уровнями транзакций (
TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ и т. д.), чтобы избежать проблем, таких как "грязное чтение" или "фантомные записи".connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
🚩Долговечность (Durability) — "данные не теряются"
После успешного завершения транзакции данные не должны теряться даже при сбоях (например, отключении электричества).
Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Какие преимущества придаёт Iterable?
- Позволяет использовать for-each цикл.
- Обеспечивает единый способ итерирования по коллекциям.
- Требует реализации метода iterator().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- Позволяет использовать for-each цикл.
- Обеспечивает единый способ итерирования по коллекциям.
- Требует реализации метода iterator().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Какие минусы Rest в высоконагруженных сис-мах?
REST – это удобный и популярный архитектурный стиль, но в высоконагруженных системах у него есть недостатки.
🚩Высокие накладные расходы HTTP (избыточность)
Проблема: Каждый REST-запрос передаёт много мета-информации (заголовки, cookies, CORS, JSON/XML).
В WebSocket/gRPC запрос выглядел бы так
🚩REST-запросы неэффективны для чатов и real-time
Проблема: REST использует "запрос-ответ", но **не поддерживает real-time.
Что происходит в REST?
1. Клиент делает HTTP-запрос к серверу.
2. Сервер обрабатывает и отправляет ответ.
3. Если клиенту нужно новое сообщение, он снова делает запрос (Polling) или использует Long Polling.
🚩Проблемы с кэшированием
Проблема: Не все REST-запросы можно кэшировать.
Кэшируются только
🚩REST API неэффективен для сложных запросов
Проблема: REST требует много отдельных запросов, если нужно загрузить связанные данные.
Пример проблемы REST:
Получить пользователя:
Получить заказы этого пользователя:
Получить детали заказов:
Ставь 👍 и забирай 📚 Базу знаний
REST – это удобный и популярный архитектурный стиль, но в высоконагруженных системах у него есть недостатки.
🚩Высокие накладные расходы HTTP (избыточность)
Проблема: Каждый REST-запрос передаёт много мета-информации (заголовки, cookies, CORS, JSON/XML).
GET /users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer token123
Content-Type: application/json
В WebSocket/gRPC запрос выглядел бы так
{ "userId": 123 }🚩REST-запросы неэффективны для чатов и real-time
Проблема: REST использует "запрос-ответ", но **не поддерживает real-time.
Что происходит в REST?
1. Клиент делает HTTP-запрос к серверу.
2. Сервер обрабатывает и отправляет ответ.
3. Если клиенту нужно новое сообщение, он снова делает запрос (Polling) или использует Long Polling.
🚩Проблемы с кэшированием
Проблема: Не все REST-запросы можно кэшировать.
Кэшируются только
GET-запросы (если сервер поддерживает ETag и Cache-Control). POST, PUT, DELETE – не кэшируются, потому что меняют данные. 🚩REST API неэффективен для сложных запросов
Проблема: REST требует много отдельных запросов, если нужно загрузить связанные данные.
Пример проблемы REST:
Получить пользователя:
/users/123 Получить заказы этого пользователя:
/users/123/orders Получить детали заказов:
/orders/456/detailsСтавь 👍 и забирай 📚 Базу знаний
👍4
🤔 Какая сложность поиска элемента в LinkedList?
Сложность поиска по индексу в LinkedList — O(n).
Это потому, что LinkedList — это цепочка узлов, и для доступа к элементу приходится перебирать узлы по одному от начала (или конца, если ближе).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Сложность поиска по индексу в LinkedList — O(n).
Это потому, что LinkedList — это цепочка узлов, и для доступа к элементу приходится перебирать узлы по одному от начала (или конца, если ближе).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍5💊1
🤔 Что знаешь про поверхностное копирование?
Поверхностное копирование (Shallow Copy) – это процесс создания нового объекта, который содержит ссылки на те же вложенные объекты, что и оригинал.
🟠Как сделать поверхностное копирование в Java?
Способ 1: Метод
🟠Проблема с вложенными объектами (общие ссылки)
Если объект содержит вложенные объекты, они не копируются, а передаются по ссылке.
🟠Как сделать глубокую копию? (Deep Copy)
Решение: Создать новый вложенный объект в
Ставь 👍 и забирай 📚 Базу знаний
Поверхностное копирование (Shallow Copy) – это процесс создания нового объекта, который содержит ссылки на те же вложенные объекты, что и оригинал.
🟠Как сделать поверхностное копирование в Java?
Способ 1: Метод
clone() (реализация Cloneable) class Person implements Cloneable {
String name;
public Person(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Поверхностное копирование
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person original = new Person("Иван");
Person copy = (Person) original.clone();
System.out.println(copy.name); // Иван
}
}🟠Проблема с вложенными объектами (общие ссылки)
Если объект содержит вложенные объекты, они не копируются, а передаются по ссылке.
class Address {
String city;
public Address(String city) { this.city = city; }
}
class User implements Cloneable {
String name;
Address address;
public User(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Поверхностное копирование
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Москва");
User original = new User("Иван", address);
User copy = (User) original.clone();
copy.address.city = "Санкт-Петербург"; // Меняем адрес у копии
System.out.println(original.address.city); // Санкт-Петербург (изменилось и у оригинала!)
}
}🟠Как сделать глубокую копию? (Deep Copy)
Решение: Создать новый вложенный объект в
clone() @Override
protected Object clone() throws CloneNotSupportedException {
User clonedUser = (User) super.clone();
clonedUser.address = new Address(this.address.city); // Копируем вложенный объект
return clonedUser;
}
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Для чего нужны паттерны программирования?
Паттерны — это решения типичных задач разработки. Они:
- повышают читаемость кода;
- упрощают поддержку;
- помогают писать гибкие и масштабируемые архитектуры;
- облегчают коммуникацию между разработчиками.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Паттерны — это решения типичных задач разработки. Они:
- повышают читаемость кода;
- упрощают поддержку;
- помогают писать гибкие и масштабируемые архитектуры;
- облегчают коммуникацию между разработчиками.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3💊1
🤔 Что такое as-if-serial semantics?
Обычный код
Что может сделать компилятор?
🚩Что можно менять? (Безопасные оптимизации)
Менять порядок инструкций, если это не влияет на результат.
Удалять лишние переменные и вычисления.
Заменять выражения константами (
Компилятор может поменять местами
🚩Что нельзя менять? (Гарантированный порядок исполнения)
Если поменять порядок
🚩Как `As-If-Serial` влияет на многопоточность?
В многопоточной среде компилятор может менять порядок команд внутри одного потока, но он не знает о другом потоке!
Опасный пример без
Решение –
Ставь 👍 и забирай 📚 Базу знаний
As-If-Serial Semantics – это принцип оптимизации компилятором, при котором код может перестраиваться, но результат его выполнения остаётся таким же, как если бы инструкции выполнялись строго по порядку. Обычный код
int a = 10;
int b = 20;
int c = a + b;
System.out.println(c);
Что может сделать компилятор?
int c = 30;
System.out.println(c);
🚩Что можно менять? (Безопасные оптимизации)
Менять порядок инструкций, если это не влияет на результат.
Удалять лишние переменные и вычисления.
Заменять выражения константами (
10 + 20 → 30). int x = 5;
int y = 10;
x = x + 1; // x = 6
System.out.println(y);
Компилятор может поменять местами
y и xint y = 10;
int x = 6;
System.out.println(y);
🚩Что нельзя менять? (Гарантированный порядок исполнения)
int x = 10;
int y = x + 5;
x = 20;
System.out.println(y);
Если поменять порядок
x = 20;
int y = x + 5; // ❌ Неверно! y теперь 25, а должно быть 15
🚩Как `As-If-Serial` влияет на многопоточность?
В многопоточной среде компилятор может менять порядок команд внутри одного потока, но он не знает о другом потоке!
Опасный пример без
volatile boolean ready = false;
int data = 0;
void writer() {
data = 42;
ready = true;
}
void reader() {
if (ready) {
System.out.println(data); // Может напечатать 0 из-за перестановки!
}
}
Решение –
volatile для readyvolatile boolean ready = false;
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Какое базовое отличие между интерфейсами Collection и List?
- Collection — базовый интерфейс, представляющий неупорядоченное множество элементов. Он не знает про индексы, дубликаты или порядок.
- List — расширяет Collection, добавляя:
- упорядоченность элементов;
- доступ по индексу;
- поддержку дубликатов.
То есть List — это частный случай Collection, который работает как последовательность с доступом по позиции.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- List — расширяет Collection, добавляя:
- упорядоченность элементов;
- доступ по индексу;
- поддержку дубликатов.
То есть List — это частный случай Collection, который работает как последовательность с доступом по позиции.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3🔥1
🤔 Какая скорость доступа к элементу в LinkedList по индексу?
Доступ к элементу по индексу в LinkedList занимает O(n).
Чтобы получить элемент, LinkedList начинает обход с начала (или конца, если индекс ближе к нему), переходя от узла к узлу. Чем ближе к началу/концу — тем быстрее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Чтобы получить элемент, LinkedList начинает обход с начала (или конца, если индекс ближе к нему), переходя от узла к узлу. Чем ближе к началу/концу — тем быстрее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4
🤔 В чём заключается разница между методами start() и run()?
🚩`start()` – создаёт новый поток
Метод
Вывод (разные потоки работают параллельно)
🚩`run()` – выполняется в ТЕКУЩЕМ потоке (без создания нового)
Если вызвать
Вывод (
Ставь 👍 и забирай 📚 Базу знаний
🚩`start()` – создаёт новый поток
Метод
start() создаёт новый поток и вызывает run() внутри него. class MyThread extends Thread {
@Override
public void run() {
System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // Запускаем новый поток
System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}Вывод (разные потоки работают параллельно)
Работает поток: main
Работает поток: Thread-0
🚩`run()` – выполняется в ТЕКУЩЕМ потоке (без создания нового)
Если вызвать
run() напрямую, код просто выполнится как обычный метод, а не в новом потоке. public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.run(); // ❌ Ошибка! Работает в главном потоке
System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}Вывод (
run() работает в главном потоке, а не в новом) Работает поток: main
Работает поток: main
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Известно ли про классы-обёртки?
Integer, Boolean, Double и др.
Позволяют:
- Использовать примитивы как объекты.
- Работать с дженериками.
- Предоставляют вспомогательные методы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Integer, Boolean, Double и др.
Позволяют:
- Использовать примитивы как объекты.
- Работать с дженериками.
- Предоставляют вспомогательные методы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔5👍2
🤔 Какая коллекция реализует дисциплину обслуживания FIFO?
FIFO (First-In, First-Out) – это принцип обработки данных: "первым вошёл – первым вышел".
🟠Коллекции, реализующие FIFO
Пример работы FIFO с
🟠Разница `poll()`, `remove()` и `peek()`
Ставь 👍 и забирай 📚 Базу знаний
FIFO (First-In, First-Out) – это принцип обработки данных: "первым вошёл – первым вышел".
🟠Коллекции, реализующие FIFO
Пример работы FIFO с
Queue import java.util.*;
public class FifoExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>(); // Можно заменить на ArrayDeque
queue.add("Первый");
queue.add("Второй");
queue.add("Третий");
System.out.println(queue.poll()); // Первый
System.out.println(queue.poll()); // Второй
System.out.println(queue.poll()); // Третий
}
}
🟠Разница `poll()`, `remove()` и `peek()`
Queue<Integer> queue = new LinkedList<>();
queue.add(10);
System.out.println(queue.peek()); // 10 (но не удаляет)
System.out.println(queue.poll()); // 10 (удаляет)
System.out.println(queue.poll()); // null (очередь пуста)
Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Какие конечные методы работы со стримами есть?
- forEach(), forEachOrdered();
- collect();
- toArray();
- reduce();
- count();
- min(), max();
- anyMatch(), allMatch(), noneMatch();
- findFirst(), findAny().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- forEach(), forEachOrdered();
- collect();
- toArray();
- reduce();
- count();
- min(), max();
- anyMatch(), allMatch(), noneMatch();
- findFirst(), findAny().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4🔥1
🤔 Как найти ошибку в программе?
Это процесс отладки (debugging), который позволяет выявить и исправить дефекты в коде. Ошибки в программе могут быть синтаксическими, логическими или связанными с выполнением программы.
1⃣Понимание ошибки
Симптомы ошибки: Программа выдает ошибочное поведение, например, неожиданный результат, исключение или сбой.
Типы ошибок:
Синтаксические: Ошибки в написании кода (например, пропущенная точка с запятой).
Логические: Код выполняется без ошибок, но результат не соответствует ожиданиям.
Ошибки выполнения: Программа завершает работу из-за исключения (например, деление на ноль).
2⃣Использование сообщений об ошибках
Компилятор/интерпретатор: Сообщает о синтаксических ошибках и указывает строку, где возникла проблема.
Стек вызовов (stack trace): Для ошибок выполнения предоставляет информацию о том, где произошла ошибка.
Пример:
3⃣Ручное исследование кода
Прочитайте проблемный участок кода и проверьте его на соответствие логике задачи.
Ищите типичные ошибки, такие как:
Неправильное использование переменных.
Ошибки в условных операторах (
Пропущенные или лишние элементы кода.
4⃣Использование инструментов отладки
Отладчик (Debugger):
Отладчики встроены в IDE, такие как IntelliJ IDEA, Eclipse или NetBeans.
Позволяют ставить точки останова (breakpoints), чтобы программа останавливалась в конкретных местах.
Позволяют пошагово выполнять код и проверять значения переменных.
Логирование (Logging):
Используйте
Пример
5⃣Тестирование
Покрытие тестами: Напишите автоматические тесты для выявления ошибки.
Используйте фреймворки, такие как JUnit или TestNG.
6⃣Анализ чужого кода
Если ошибка в сторонней библиотеке, проверьте документацию и известные проблемы. Убедитесь, что вы правильно используете методы и классы.
7⃣Рефакторинг и исправление
Исправьте ошибку, убедившись, что исправление не приводит к новым ошибкам. Проверьте весь код на предмет аналогичных ошибок.
Ставь 👍 и забирай 📚 Базу знаний
Это процесс отладки (debugging), который позволяет выявить и исправить дефекты в коде. Ошибки в программе могут быть синтаксическими, логическими или связанными с выполнением программы.
1⃣Понимание ошибки
Симптомы ошибки: Программа выдает ошибочное поведение, например, неожиданный результат, исключение или сбой.
Типы ошибок:
Синтаксические: Ошибки в написании кода (например, пропущенная точка с запятой).
Логические: Код выполняется без ошибок, но результат не соответствует ожиданиям.
Ошибки выполнения: Программа завершает работу из-за исключения (например, деление на ноль).
2⃣Использование сообщений об ошибках
Компилятор/интерпретатор: Сообщает о синтаксических ошибках и указывает строку, где возникла проблема.
Стек вызовов (stack trace): Для ошибок выполнения предоставляет информацию о том, где произошла ошибка.
Пример:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:5)
3⃣Ручное исследование кода
Прочитайте проблемный участок кода и проверьте его на соответствие логике задачи.
Ищите типичные ошибки, такие как:
Неправильное использование переменных.
Ошибки в условных операторах (
if, switch).Пропущенные или лишние элементы кода.
4⃣Использование инструментов отладки
Отладчик (Debugger):
Отладчики встроены в IDE, такие как IntelliJ IDEA, Eclipse или NetBeans.
Позволяют ставить точки останова (breakpoints), чтобы программа останавливалась в конкретных местах.
Позволяют пошагово выполнять код и проверять значения переменных.
Логирование (Logging):
Используйте
System.out.println для вывода промежуточных данных: System.out.println("Value of x: " + x);
Пример
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
int x = 10;
int y = 0;
try {
int result = x / y;
} catch (ArithmeticException e) {
logger.error("Division by zero!", e);
}
}
}
5⃣Тестирование
Покрытие тестами: Напишите автоматические тесты для выявления ошибки.
Используйте фреймворки, такие как JUnit или TestNG.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
@Test
void testAddition() {
assertEquals(5, Calculator.add(2, 3));
}
}
6⃣Анализ чужого кода
Если ошибка в сторонней библиотеке, проверьте документацию и известные проблемы. Убедитесь, что вы правильно используете методы и классы.
7⃣Рефакторинг и исправление
Исправьте ошибку, убедившись, что исправление не приводит к новым ошибкам. Проверьте весь код на предмет аналогичных ошибок.
Ставь 👍 и забирай 📚 Базу знаний
👍2🔥1
🤔 Что такое партиционирование?
Это разделение таблицы на логические части (партиции) для улучшения производительности и управляемости.
1. Партиции могут быть основаны на диапазонах, хэшах или списках значений.
2. Улучшает производительность запросов, снижая объём обрабатываемых данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
1. Партиции могут быть основаны на диапазонах, хэшах или списках значений.
2. Улучшает производительность запросов, снижая объём обрабатываемых данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍6
🤔 Как бороться в БД с SQL Injection?
SQL Injection – это атака, при которой злоумышленник вставляет вредоносный SQL-код в запрос, чтобы получить несанкционированный доступ к данным.
Допустим, у нас есть код
Если злоумышленник введёт
🚩Способы защиты от SQL Injection
🟠Использование `PreparedStatement` (РЕКОМЕНДУЕТСЯ)
Подготовленные запросы автоматически экранируют входные данные, предотвращая SQL-инъекции.
🟠Использование ORM (например, Hibernate)
ORM-фреймворки (Hibernate, JPA) автоматически генерируют безопасные SQL-запросы.
🟠Проверка и экранирование входных данных
Если по какой-то причине
🟠Минимизация прав в БД
Создавайте отдельного пользователя БД с ограниченными правами:
Запрет на
Только доступ к нужным таблицам
🟠Использование Web Application Firewall (WAF)
WAF анализирует HTTP-запросы и блокирует подозрительные SQL-запросы. Пример: ModSecurity – популярный WAF для защиты веб-приложений.
Ставь 👍 и забирай 📚 Базу знаний
SQL Injection – это атака, при которой злоумышленник вставляет вредоносный SQL-код в запрос, чтобы получить несанкционированный доступ к данным.
Допустим, у нас есть код
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
Если злоумышленник введёт
' OR '1'='1 в поле пароля, запрос превратится в: SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'
🚩Способы защиты от SQL Injection
🟠Использование `PreparedStatement` (РЕКОМЕНДУЕТСЯ)
Подготовленные запросы автоматически экранируют входные данные, предотвращая SQL-инъекции.
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
🟠Использование ORM (например, Hibernate)
ORM-фреймворки (Hibernate, JPA) автоматически генерируют безопасные SQL-запросы.
TypedQuery<User> query = entityManager.createQuery(
"SELECT u FROM User u WHERE u.username = :username AND u.password = :password", User.class);
query.setParameter("username", username);
query.setParameter("password", password);
User user = query.getSingleResult();
🟠Проверка и экранирование входных данных
Если по какой-то причине
PreparedStatement использовать нельзя, экранируйте опасные символы (', " и ;). String safeInput = input.replace("'", "\\'");🟠Минимизация прав в БД
Создавайте отдельного пользователя БД с ограниченными правами:
Запрет на
DROP, DELETE, UPDATE без WHERE Только доступ к нужным таблицам
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'securepassword';
GRANT SELECT, INSERT, UPDATE ON mydb.users TO 'app_user'@'localhost';
🟠Использование Web Application Firewall (WAF)
WAF анализирует HTTP-запросы и блокирует подозрительные SQL-запросы. Пример: ModSecurity – популярный WAF для защиты веб-приложений.
Ставь 👍 и забирай 📚 Базу знаний
👍3🔥1
🤔 Какое худшее время работы метода contains() в ArrayList?
O(n) — также линейный поиск, т.к. нет хеширования.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
O(n) — также линейный поиск, т.к. нет хеширования.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2
🤔 Для чего нужен функциональный интерфейс BiConsumer<T,U>?
Сигнатура
🚩Вывод пар значений
Допустим, у нас есть
Вывод
🚩Использование `BiConsumer` в `Stream`
Допустим, у нас есть список продуктов и их цены. Мы хотим увеличить цену каждого товара и напечатать результат.
Вывод
🚩Объединение `BiConsumer` с `andThen()`
Метод
Вывод:
Ставь 👍 и забирай 📚 Базу знаний
BiConsumer<T, U> — это функциональный интерфейс из пакета java.util.function, который принимает два входных аргумента и не возвращает результат. Сигнатура
BiConsumer<T, U>@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
🚩Вывод пар значений
Допустим, у нас есть
Map<String, Integer>, и мы хотим вывести все ключи и значения: import java.util.Map;
import java.util.function.BiConsumer;
public class BiConsumerExample {
public static void main(String[] args) {
Map<String, Integer> map = Map.of("Alice", 30, "Bob", 25, "Charlie", 35);
// Используем BiConsumer для вывода ключа и значения
BiConsumer<String, Integer> printEntry = (key, value) ->
System.out.println("Имя: " + key + ", возраст: " + value);
// Применяем BiConsumer к каждому элементу Map
map.forEach(printEntry);
}
}
Вывод
Имя: Alice, возраст: 30
Имя: Bob, возраст: 25
Имя: Charlie, возраст: 35
🚩Использование `BiConsumer` в `Stream`
Допустим, у нас есть список продуктов и их цены. Мы хотим увеличить цену каждого товара и напечатать результат.
import java.util.*;
import java.util.function.BiConsumer;
public class BiConsumerStreamExample {
public static void main(String[] args) {
Map<String, Double> products = new HashMap<>();
products.put("Хлеб", 50.0);
products.put("Молоко", 80.0);
products.put("Яблоки", 120.0);
// BiConsumer, который увеличивает цену и выводит её
BiConsumer<String, Double> increaseAndPrint = (name, price) -> {
double newPrice = price * 1.1; // +10%
System.out.println(name + " теперь стоит " + newPrice);
};
products.forEach(increaseAndPrint);
}
}
Вывод
Хлеб теперь стоит 55.0
Молоко теперь стоит 88.0
Яблоки теперь стоят 132.0
🚩Объединение `BiConsumer` с `andThen()`
Метод
andThen(BiConsumer<T, U>) позволяет объединять несколько действий в цепочку. import java.util.function.BiConsumer;
public class BiConsumerChaining {
public static void main(String[] args) {
BiConsumer<String, Integer> printUser = (name, age) ->
System.out.println("Пользователь: " + name + ", возраст: " + age);
BiConsumer<String, Integer> checkAdult = (name, age) ->
System.out.println(name + (age >= 18 ? " совершеннолетний" : " несовершеннолетний"));
// Объединяем два BiConsumer'а
BiConsumer<String, Integer> combined = printUser.andThen(checkAdult);
combined.accept("Алексей", 20);
combined.accept("Мария", 16);
}
}
Вывод:
Пользователь: Алексей, возраст: 20
Алексей совершеннолетний
Пользователь: Мария, возраст: 16
Мария несовершеннолетний
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Что такое шаблон Event Sourcing?
Event Sourcing — это подход, при котором вся история изменений состояния хранится как последовательность событий.
Плюсы:
- можно восстановить любое состояние;
- идеален для аудита и CQRS.
Минусы:
- сложно мигрировать;
- высокая сложность чтения без проекций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Event Sourcing — это подход, при котором вся история изменений состояния хранится как последовательность событий.
Плюсы:
- можно восстановить любое состояние;
- идеален для аудита и CQRS.
Минусы:
- сложно мигрировать;
- высокая сложность чтения без проекций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥2
🤔 Какая структура данных в коллекции List?
В Java интерфейс
🚩Основные реализации `List` и их структуры данных
🟠ArrayList
Динамический массив
Структура данных: массив
Быстрая индексация
🟠LinkedList
Двусвязный список
Структура данных: двусвязный список
Быстрое добавление/удаление элементов
🟠Vector
Динамический массив (синхронизирован)
Структура данных: массив (как
Устарел, используется редко из-за
Ставь 👍 и забирай 📚 Базу знаний
В Java интерфейс
List представляет упорядоченную коллекцию элементов, допускающую дубликаты. В зависимости от конкретной реализации (ArrayList, LinkedList, Vector), используется разная структура данных. 🚩Основные реализации `List` и их структуры данных
🟠ArrayList
Динамический массив
Структура данных: массив
Быстрая индексация
O(1), но медленное удаление/вставка в середину O(n). List<String> list = new ArrayList<>();
🟠LinkedList
Двусвязный список
Структура данных: двусвязный список
Быстрое добавление/удаление элементов
O(1), но медленный доступ по индексу O(n). List<String> list = new LinkedList<>();
🟠Vector
Динамический массив (синхронизирован)
Структура данных: массив (как
ArrayList), но с синхронизацией. Устарел, используется редко из-за
synchronized методов (медленнее ArrayList). List<String> list = new Vector<>();
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Какие есть виды объединения веток?
- Merge — объединяет изменения, создаёт новый коммит слияния;
- Rebase — переносит коммиты на другую ветку, изменяя их историю;
- Squash — объединяет несколько коммитов в один перед слиянием;
- Fast-forward — слияние без нового коммита, если нет расхождений.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- Merge — объединяет изменения, создаёт новый коммит слияния;
- Rebase — переносит коммиты на другую ветку, изменяя их историю;
- Squash — объединяет несколько коммитов в один перед слиянием;
- Fast-forward — слияние без нового коммита, если нет расхождений.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2🔥1