Java | Вопросы собесов
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
Больше📈 Аналитический обзор Telegram-канала Java | Вопросы собесов
Канал Java | Вопросы собесов (@easy_java_ru) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 11 390 подписчиков, занимая 10 546 место в категории Технологии и приложения и 56 220 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 11 390 подписчиков.
Согласно последним данным от 29 августа, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило -7, а за последние 24 часа — -2, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 8.95%. В первые 24 часа после публикации контент обычно набирает 5.86% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 1 020 просмотров. В течение первых суток публикация набирает 668 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 3.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как ставь, void, string, строка, static.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy
Контакт для рекламы: @easyoffer_adv”
Благодаря высокой частоте обновлений (последние данные получены 30 августа, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
@OneToMany, @ManyToMany.
@Entity
class User {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders; // Загрузятся ТОЛЬКО при первом вызове getOrders()
}
User user = session.get(User.class, 1L); // Загружается только User
List<Order> orders = user.getOrders(); // Запрос в БД выполняется ТОЛЬКО здесь
🚩Eager Fetching (жадная загрузка)
Hibernate загружает все связанные данные сразу, даже если они не нужны.
Увеличивает время выполнения запроса, так как делает JOIN или несколько отдельных запросов.
Используется по умолчанию в @ManyToOne, @OneToOne.
@Entity
class User {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
private List<Order> orders; // Загружается сразу при получении User
}
User user = session.get(User.class, 1L); // Загружается User + сразу все его Orders
Ставь 👍 и забирай 📚 Базу знанийforEach позволяет компактно и удобно итерировать по элементам коллекций.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
🟠Фильтрация и преобразование коллекций
С использованием Stream API и лямбда-выражений можно легко фильтровать, сортировать и преобразовывать коллекции.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
filteredNames.forEach(System.out::println); // Вывод: Alice
🟠Сортировка коллекций
Лямбда-выражения упрощают сортировку коллекций с использованием метода sort.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((name1, name2) -> name1.compareTo(name2));
names.forEach(System.out::println);
🟠Использование функциональных интерфейсов
Лямбда-выражения широко используются с функциональными интерфейсами, такими как Predicate, Function, Consumer и Supplier.
// Predicate
Predicate<String> startsWithA = s -> s.startsWith("A");
boolean result = startsWithA.test("Alice"); // true
// Function
Function<String, Integer> lengthFunction = s -> s.length();
int length = lengthFunction.apply("Hello"); // 5
// Consumer
Consumer<String> printConsumer = s -> System.out.println(s);
printConsumer.accept("Hello, World!"); // Вывод: Hello, World!
// Supplier
Supplier<String> stringSupplier = () -> "Hello, Supplier!";
String suppliedString = stringSupplier.get();
System.out.println(suppliedString); // Вывод: Hello, Supplier!
🟠Параллельные вычисления
Лямбда-выражения с использованием параллельных потоков позволяют легко выполнять параллельные вычисления.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum: " + sum); // Вывод: Sum: 15
🚩Пример использования в реальном проекте
Предположим, у нас есть список сотрудников, и мы хотим отфильтровать и отсортировать их по имени.
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + '}';
}
}
public class LambdaExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 30),
new Employee("Bob", 25),
new Employee("Charlie", 35),
new Employee("David", 28)
);
// Фильтрация и сортировка сотрудников по имени
List<Employee> filteredAndSorted = employees.stream()
.filter(e -> e.getAge() > 27)
.sorted(Comparator.comparing(Employee::getName))
.collect(Collectors.toList());
filteredAndSorted.forEach(System.out::println);
}
}
Ставь 👍 и забирай 📚 Базу знаний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 (очередь пуста)
Ставь 👍 и забирай 📚 Базу знанийString) являются неизменяемыми (immutable) объектами и обрабатываются особым образом, особенно при их создании.
🚩`"Hello"` — строка из пула строк
Когда вы пишете:
String str1 = "Hello";
🚩`new String("Hello")` — создание нового объекта
Когда вы создаёте строку так:
String str2 = new String("Hello");
🚩Разница в сравнении строк
public class StringTest {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1 == str2); // true (ссылаются на один объект в пуле)
System.out.println(str1 == str3); // false (разные объекты в памяти)
System.out.println(str1.equals(str3)); // true (содержимое одинаковое)
}
}
🚩Когда использовать `new String()`?
В 99% случаев new String() не нужен. Его создание расходует память и снижает производительность.
Но он может быть полезен, если вы намеренно хотите создать новый объект, например, для защиты от изменения ссылок:
String safeCopy = new String(originalString); // Теперь это точно отдельный объект
Ставь 👍 и забирай 📚 Базу знанийPrintWriter и ServletOutputStream в одном сервлете нельзя. Это связано с тем, что эти два класса работают с разными типами данных и открывают ответный поток в разных режимах — PrintWriter для символьных данных, а ServletOutputStream для байтовых данных.
🚩Почему нельзя использовать одновременно:
Типы потоков:
🟠`PrintWriter`: Предназначен для записи текстовых данных (символов и строк).
🟠`ServletOutputStream`: Предназначен для записи бинарных данных (байтов и массивов байтов).
Конфликт потоков: Открытие одного потока блокирует возможность открытия другого. Попытка использования обоих потоков в одном запросе приведет к исключению IllegalStateException.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
public class MixedContentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
ServletOutputStream outputStream = response.getOutputStream(); // Это вызовет IllegalStateException
writer.println("Hello, World!"); // Пытаемся записать текст
byte[] imageData = ...; // Получаем бинарные данные
outputStream.write(imageData); // Пытаемся записать бинарные данные
}
}
Если требуется отправить как текстовые, так и бинарные данные, это нужно делать последовательно, разделяя логику на отдельные запросы или сервлеты.
Отправка текстовых данных:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
public class TextServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body><h1>Hello, World!</h1></body></html>");
}
}
Отправка бинарных данных:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;
public class BinaryServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/pdf");
ServletOutputStream out = response.getOutputStream();
byte[] pdfData = ...; // Получаем PDF данные
out.write(pdfData);
}
}
Ставь 👍 и забирай 📚 Базу знаний@Component помечает класс как Spring-бин (компонент).
Является универсальной аннотацией.
Можно применять к любым классам, которые должны управляться Spring-контейнером.
@Component
public class MyComponent {
public void doWork() {
System.out.println("Работа компонента");
}
}
🚩`@Service` – для бизнес-логики
@Service – это специализированный @Component, используемый для сервисных классов (логика приложения).
Упрощает понимание кода (показывает, что этот класс содержит бизнес-логику).
@Service
public class UserService {
public String getUser() {
return "Пользователь Иван";
}
}
🚩`@Repository` – для работы с базой данных
@Repository – это специализированный @Component для слоя доступа к данным (DAO, Repository).
Автоматически перехватывает SQL-исключения (PersistenceExceptionTranslationPostProcessor) и преобразует их в DataAccessException.
@Repository
public class UserRepository {
public String findUserById(int id) {
return "Пользователь с ID " + id;
}
}
Ставь 👍 и забирай 📚 Базу знанийOldCharger, который работает с вольтажем 220V, а мы хотим, чтобы он работал с USB (5V).
Старый интерфейс (неподходящий)
class OldCharger {
void charge220V() {
System.out.println("Зарядка 220V...");
}
}
Новый интерфейс (нужный)
interface USBCharger {
void charge5V();
}
Адаптер, который превращает 220V в 5V
class ChargerAdapter implements USBCharger {
private OldCharger oldCharger;
public ChargerAdapter(OldCharger oldCharger) {
this.oldCharger = oldCharger;
}
@Override
public void charge5V() {
System.out.println("Преобразуем 220V в 5V...");
oldCharger.charge220V();
}
}
Использование адаптера
public class Main {
public static void main(String[] args) {
OldCharger oldCharger = new OldCharger();
USBCharger adapter = new ChargerAdapter(oldCharger);
adapter.charge5V(); // Теперь старая зарядка работает с 5V!
}
}
Object Adapter (адаптер-объект) – использует композицию (пример выше).
Class Adapter (адаптер-класс) – использует наследование (extends).
class ChargerAdapter extends OldCharger implements USBCharger {
@Override
public void charge5V() {
System.out.println("Преобразуем 220V в 5V...");
charge220V();
}
}
Ставь 👍 и забирай 📚 Базу знанийint занимает 4 байта (32 бита) и имеет диапазон:
-2^{31} \text{ до } 2^{31} - 1
🚩Точный диапазон `int`
🟠Минимальное значение
Integer.MIN_VALUE = -2,147,483,648
🟠Максимальное значение
Integer.MAX_VALUE = 2,147,483,647
public class Main {
public static void main(String[] args) {
System.out.println("Минимальный int: " + Integer.MIN_VALUE);
System.out.println("Максимальный int: " + Integer.MAX_VALUE);
}
}
Вывод:
Минимальный int: -2147483648 Максимальный int: 2147483647🚩Почему именно такой диапазон? 4 байта (32 бита) означают, что у нас 2³² возможных значений. Поскольку
int знаковый (поддерживает отрицательные и положительные числа), половина значений отводится подотрицательные числа.
Один бит используется для знака (0 – положительное число, 1 – отрицательное).
\text{Диапазон} = - (2^{31}) \text{ до } (2^{31} - 1)
🚩Что будет, если выйти за пределы `int`?
Если сложить два максимальных значения int, произойдёт переполнение (overflow)
int a = Integer.MAX_VALUE;
int b = 1;
int c = a + b;
System.out.println(c); // Выведет -2147483648 (переполнение!)
🟠Как работать с числами больше `int`?
Использовать `long` (8 байт, диапазон от -2^63 до 2^63 - 1):
long bigNumber = 2_147_483_648L; // Обязательно добавлять "L" в конце
Использовать BigInteger (неограниченный размер):
BigInteger bigNum = new BigInteger("999999999999999999999999");
Ставь 👍 и забирай 📚 Базу знаний