J
Java | Фишки и трюки
14.07.2026 12:27 · 👁 522
☕️Использование классов Pattern и Matcher
Pattern и Matcher - это классы, предоставляемые Java для работы с регулярными выражениями. Pattern используется для компиляции регулярного выражения, а Matcher используется для сравнения этого выражения с определенной последовательностью символов.
➡️Пример использования Pattern и Matcher:
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String text = "The cat in the hat";
// Компилируем регулярное выражение
Pattern pattern = Pattern.compile("\\bcat\\b");
// Создаем Matcher, сравниваем его с текстом и выводим результат
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("Найдено совпадение!");
} else {
System.out.println("Совпадений не найдено");
}
}
}
🔹В данном примере мы создаем регулярное выражение, которое ищет слово "cat" как отдельное слово. Затем мы создаем Matcher, который сравнивает это выражение с текстом "The cat in the hat". Результатом выполнения программы будет сообщение "Найдено совпадение!", так как слово "cat" есть в тексте.
📌Pattern и Matcher позволяют удобно работать с регулярными выражениями и обрабатывать текстовые данные. Они широко используются в поиске и замене текста, валидации ввода и других задачах, связанных с обработкой строк.
J
Java | Фишки и трюки
09.07.2026 09:58 · 👁 931
⌨️ Effectively final - это термин, который используется для описания переменной в Java, которая фактически ведет себя как final, хотя она не объявлена с ключевым словом final. То есть, хотя вы можете изменять значение этой переменной, вы это не делаете. Компилятор Java позволяет использовать такие переменные в лямбда-выражениях и анонимных классах, даже если они не объявлены как final.
В примере переменная x объявлена с ключевым словом final, поэтому ее значение не может быть изменено. Переменная y не объявлена как final, но внутри метода она не изменяется после инициализации, поэтому она считается "effectively final" и может быть использована в анонимных классах и лямбда-выражениях.
J
Java | Фишки и трюки
07.07.2026 10:12 · 👁 908
☕️Использование ORM фреймворков
ORM (Object-Relational Mapping) фреймворки в Java позволяют программистам работать с базами данных, представляя данные в виде объектов, что упрощает процесс взаимодействия с БД. Несколько популярных технологий:
1. JPA (Java Persistence API): Стандартная спецификация для работы с объектно-реляционным отображением в Java. Пример использования JPA с Hibernate провайдером:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Employee employee = new Employee("Jane", "Smith", 1200);
em.persist(employee);
em.getTransaction().commit();
em.close();
2. Hibernate: Один из наиболее широко используемых ORM-фреймворков в Java. Пример кода для сохранения объекта в базе данных с использованием Hibernate:
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Employee employee = new Employee("John", "Doe", 1000);
session.save(employee);
session.getTransaction().commit();
session.close();
3. Spring Data JPA: Часть Spring Data, облегчающая работу с JPA. Пример использования Spring Data JPA для поиска сущности по идентификатору:
Employee employee = employeeRepository.findById(1L).orElse(null);
4. MyBatis: Фреймворк, который предоставляет более SQL-центричный подход к ORM. Пример маппинга объекта на SQL запрос с помощью MyBatis:
<select id="selectEmployeeById" resultType="Employee">
SELECT * FROM employees WHERE id = #{id}
</select>
ORM фреймворки упрощают работу с базами данных в Java, позволяя разработчикам оперировать объектами вместо SQL запросов, что улучшает производительность и поддерживаемость кода. Каждый из перечисленных фреймворков имеет свои особенности и преимущества, поэтому выбор зависит от конкретных потребностей проекта.
J
Java | Фишки и трюки
06.07.2026 09:29 · 👁 785
⌨️ Что такое перечисления (enum)?
Перечисления представляют набор логически связанных констант. Нужны для ограничения области допустимых значений: например, времена года, дни недели.
Перечисление фактически представляет новый класс, поэтому мы можем определить переменную данного типа и использовать ее.
Перечисления, как и обычные классы, могут определять конструкторы, поля и методы.
Следует отметить, что конструктор по умолчанию приватный.
Преимуществом Еnum перед обычными константами является возможность проверки типа данных.
К недостаткам относится невозможность применения операторов >, <, >=, <=, а так же большее потребление памяти по сравнению с обычными константами.
Встроенные методы:
- ordinal() возвращает порядковый номер определенной константы (нумерация начинается с 0)
- values() возвращает массив всех констант перечисления
public enum Day {
MONDAY("понедельник"),
TUESDAY("вторник"),
WEDNESDAY("среда"),
THURSDAY("четверг"),
FRIDAY("пятница"),
SATURDAY("суббота"),
SUNDAY("воскресенье");
Day(String value) {
this.value = value;
}
String value;
public String getValue() {
return value;
}
}
public class EnumClass {
public static void main(String[] args) {
System.out.println(message(Day.FRIDAY));
}
public static String message(Day day) {
return "Это " + day.getValue();
// Это пятница
}
}
J
Java | Фишки и трюки
03.07.2026 15:10 · 👁 975
⌨️ Как ^, | и & работают с целочисленными операндами
Пример:
int a = 3 & 5;
int b = 3 | 5;
int c = 3 ^ 5;
System.out.println(a); // 1
System.out.println(b); // 7
System.out.println(c); // 6
Чтобы думать как Java, нужно:
✅ Перевести значения обоих операндов в двоичную систему счисления.
✅ Расположить результаты перевода друг под другом.
✅ Сравнять в них число разрядов (дополнить лидирующими нулями).
✅ Применить к битам из каждого столбца оператор (&, | или ^).
✅ Записать результат каждой операции ниже в том же столбце.
✅ Перевести итог в десятичную форму.
Потренеруемся на примере 3 & 5:
Число 3 в двоичной системе счисления имеет вид 11, а число 5 — 101.
Так как у числа 5 три разряда в двоичной системе, а у числа 3 — всего два, добавим лидирующий ноль к числу 3 в двоичной системе и получим 011.
Берём цифры из обоих чисел и применяем к ним попарно оператор & (AND):
011
&&&
101
===
001
Получаем число 001. В десятичной записи ему соответствует число 1. Поэтому операция 3 & 5 и возвращает в результате 1.
J
Java | Фишки и трюки
02.07.2026 16:20 · 👁 957
⌨️ Полезные стримы. Группировка
Дан список людей с именем и городом проживания. Нужно сгруппировать их по городам.
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
record Person(String name, String city) {}
public class StreamExample {
public static void main(String[] args) {
List<Person> people = List.of(
new Person("Alice", "New York"),
new Person("Bob", "Los Angeles"),
new Person("Charlie", "New York"),
new Person("David", "Los Angeles"),
new Person("Edward", "San Francisco")
);
Map<String, List<Person>> peopleByCity = people.stream()
.collect(Collectors.groupingBy(Person::city));
peopleByCity.forEach((city, peopleInCity) -> {
System.out.println(city + ": " + peopleInCity.stream()
.map(Person::name)
.collect(Collectors.joining(", ")));
});
// Вывод:
// San Francisco: Edward
// New York: Alice, Charlie
// Los Angeles: Bob, David
}
}
#java #stream #grouping
J
Java | Фишки и трюки
30.06.2026 13:01 · 👁 969
⌨️ Параллельные и последовательные потоки (Stream)
Последовательные потоки (Sequential Streams)
✔️ Обрабатывают элементы последовательно, один за другим, на одном потоке, следовательно производительность ограничена возможностями одного ядра процессора.
✔️ Используют основной поток программы (main thread) для выполнения операций.
✔️ Метод stream() создаёт последовательный поток.
Пример последовательного потока:
List<String> list = List.of("Hello ", "w", "o", "r", "l", "d!");
list.stream().forEach(System.out::print);
// Hello world!
Параллельные потоки (Parallel Streams)
✔️ Обрабатывают элементы параллельно, распределяя их между несколькими потоками (threads), что позволяет использовать многопоточность.
✔️ Используют ForkJoinPool для распределения задач между потоками.
✔️ Эффективны для больших наборов данных, поскольку могут улучшить производительность на многоядерных процессорах.
✔️ Параллельный поток можно создать, вызвав метод parallelStream() или применив метод parallel() к уже существующему потоку.
Пример параллельного потока:
List<String> list = List.of("Hello ", "w", "o", "r", "l", "d!");
list.parallelStream().forEach(System.out::print);
// rlHello d!wo
#java #Stream #parallelStream
J
Java | Фишки и трюки
27.06.2026 08:30 · 👁 1.2K
⌨️ ForkJoinPool — это специальная реализация пула потоков, предназначенная для выполнения параллельных задач с использованием алгоритма разделяй и властвуй (divide and conquer). Этот пул потоков был представлен в Java 7 как часть библиотеки java.util.concurrent.
Использует подход "разделяй и властвуй", где задача разбивается на подзадачи до тех пор, пока они не станут достаточно маленькими для последовательного решения. Для этого используются классы RecursiveTask<V> (возвращает результат) и RecursiveAction (без результата).
ForkJoinPool динамически управляет количеством потоков, при необходимости создавая новые. Обычно это количество соответствует числу процессоров, доступных в системе.
Использует технику work-stealing, где потоки, завершившие свои задачи, могут "красть" задачи у других потоков, чтобы эффективно использовать ресурсы процессора.
ForkJoinPool обладает высокой производительностью для задач, которые можно разбить на независимые подзадачи.
Основные методы:
invoke(): синхронно запускает задачу и ждет её завершения.
submit(): запускает задачу асинхронно.
execute(): также запускает задачу асинхронно, но не возвращает результат.
Пример использования:
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
private final int threshold = 10;
public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if (end - start <= threshold) {
// Базовый случай: небольшая задача
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Разделяем задачу
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);
leftTask.fork(); // Асинхронно запускаем левую подзадачу
int rightResult = rightTask.compute(); // Синхронно вычисляем правую подзадачу
int leftResult = leftTask.join(); // Ждем завершения левой подзадачи
return leftResult + rightResult;
}
}
}
public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
SumTask task = new SumTask(array, 0, array.length);
int result = pool.invoke(task);
System.out.println("Сумма: " + result);
}
}
Этот код создает задачу для суммирования массива, разбивая его на подзадачи.
#java #ForkJoinPool
J
Java | Фишки и трюки
23.06.2026 09:04 · 👁 1.3K
⌨️ Stream.reduce() vs Collectors.joining()
Когда требуется конкатенировать строки с использованием Stream, можно выбрать один из двух методов: Stream.reduce() или Stream.collect(Collectors.joining()).
Пример с Stream.reduce():
List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().reduce("", (a, b) -> a + b);
System.out.println(result); // Str1Str2Str3
Пример с Collectors.joining():
List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().collect(Collectors.joining());
System.out.println(result); // Str1Str2Str3
Использование reduce() для конкатенации строк не является оптимальным с точки зрения производительности. При каждом вызове операции +, создается новая строка, так как строки в Java неизменяемы. Это приводит к увеличению нагрузки на память из-за создания множества промежуточных объектов.
В свою очередь, метод Collectors.joining() использует StringBuilder для сборки строк, что значительно эффективнее. Он избегает создания лишних объектов и снижает потребление памяти.
#java #Stream #reduce #joining
J
Java | Фишки и трюки
22.06.2026 14:23 · 👁 1.2K
⌨️ POJO (Plain Old Java Object) — это простой Java-объект, не зависящий от каких-либо специфичных библиотек, фреймворков или технологий. Такой объект обычно содержит только поля (атрибуты) и методы доступа (геттеры и сеттеры), без дополнительной логики, аннотаций или наследования от специфических классов.
Пример POJO:
public class Person {
private String name;
private int age;
// Конструктор
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Геттеры и сеттеры
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
POJO используется для создания простых объектов без привязки к какой-либо специфической архитектуре или фреймворку. Например, в JPA объекты-сущности часто являются POJO, что позволяет их использовать независимо от платформы.
#java #pojo