
- Главная
- Каталог
- Интернет технологии
- Java | Фишки и трюки
Java | Фишки и трюки
Аудитория канала - начинающие или опытные Java программисты. Канал о разработке приложений на Java, в том числе написание бэкенд и web-приложений. Рассматриваются фишки и трюки при программировании на Java.
Статистика канала
Enum.
Внутренне EnumMap использует массив для хранения значений, где индекс массива соответствует порядковому номеру (ordinal()) элемента перечисления. Это делает его быстрее, чем хэш-таблицы (HashMap) и более экономным по памяти.
EnumMap хранит ключи в порядке их объявления в перечислении, что отличает его от большинства других Map (кроме LinkedHashMap).
Так как ключи строго ограничены перечислением, это снижает вероятность ошибок при разработке.
🔍 Пример:
import java.util.EnumMap;
enum Action {
START, STOP, PAUSE
}
public class EnumMapExample {
public static void main(String[] args) {
EnumMap<Action, Runnable> actionMap = new EnumMap<>(Action.class);
// Определяем поведение для каждого значения Enum
actionMap.put(Action.START, () -> System.out.println("Starting the process..."));
actionMap.put(Action.STOP, () -> System.out.println("Stopping the process..."));
actionMap.put(Action.PAUSE, () -> System.out.println("Pausing the process..."));
// Пример вызова
Action currentAction = Action.START;
actionMap.get(currentAction).run();
}
}{}
#Java #EnumMapThreadLocal выглядит как магия:
У каждого потока будет своё собственное значение
И это правда. Но именно из-за этого он часто становится источником очень неприятных багов в production.
📦 Как работает ThreadLocal
ThreadLocal<String> currentUser = new ThreadLocal<>();
currentUser.set("Alex");{}
Теперь в каждом потоке хранится своё значение:
System.out.println(currentUser.get());{}
🔥 Где это используют
* Spring Security
* Hibernate
* логирование (`traceId`)
* транзакции
* хранение request context
🤔 Кажется идеально. В чём проблема?
Проблема начинается с thread pool.
⚠️ Главная ловушка
ThreadLocal<String> local = new ThreadLocal<>();
executor.submit(() -> {
local.set("DATA");
});{}
Поток из пула НЕ уничтожается после задачи.
👉 Значение остаётся висеть внутри потока.
💣 Что это вызывает
* утечки памяти
* неожиданные данные между запросами
* "рандомные" баги в серверных приложениях
😨 Самое неприятное
Даже если сам ThreadLocal удалён GC,
значение внутри потока может продолжать жить.
Почему?
Потому что внутри Thread:
* ключ (`ThreadLocal`) хранится как weak reference
* а значение - как strong reference
👉 Ключ умер
👉 Значение осталось
Классическая hidden memory leak.
✅ Правильный подход
ВСЕГДА чистить ThreadLocal:
try {
local.set("DATA");
// работа
} finally {
local.remove();
}{}
🚀 Почему это критично в Spring / Tomcat
Сервер использует thread pool:
* один поток обслуживает тысячи запросов
* забытый ThreadLocal живёт очень долго
Отсюда:
* рост памяти
* странное поведение пользователей
* “невоспроизводимые” баги
🧠 Интересный факт
ThreadLocal не хранит данные “в себе”.
Наоборот:
👉 каждый Thread хранит ThreadLocalMap
То есть данные лежат внутри потока, а не объекта ThreadLocal.Comparator и Comparable
В Java для сортировки объектов используются два ключевых интерфейса: Comparable и Comparator. Понимание их отличий и применения поможет вам эффективно управлять сортировкой данных в коллекциях.
📚 Краткие определения:
- Comparable:
- Используется, когда класс должен иметь естественный порядок. Например, мы можем сортировать людей по возрасту.
- Сигнатура метода: int compareTo(T o).
Пример:
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // Сравнение по возрасту
}
}{}
- Comparator:
- Используется для создания внешних стратегий сравнения, позволяя определять несколько способов сортировки. Подходит для сортировки объектов разных классов.
- Сигнатура метода: int compare(T o1, T o2).
Пример:
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name); // Сравнение по имени
}
}{}
⚖️ Когда использовать:
- Comparable:
- Используйте, если у класса есть естественный порядок. Например, чтобы сортировать людей по возрасту.
- Сортировка с помощью Collections.sort() или Arrays.sort() будет проще.
Пример использования:
List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 25));
Collections.sort(people); // Сортировка по возрасту с использованием Comparable{}
- Comparator:
- Идеален для ситуаций, когда необходимо изменить порядок сортировки или сравнивать объекты разных классов.
Пример использования:
List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 25));
Collections.sort(people, new NameComparator()); // Сортировка по имени с использованием Comparator{}
#java #Comparator #Comparablepublic abstract или (начиная с Java 8) default - методами с реализацией по-умолчанию, а поля - public static final.
✔️ Интерфейсы позволяют создавать структуры типов без иерархии.
✔️ Наследуясь от абстрактного, класс «растворяет» собственную индивидуальность. Реализуя интерфейс, он расширяет собственную функциональность.
Абстрактные классы содержат частичную реализацию, которая дополняется или расширяется в подклассах. При этом все подклассы схожи между собой в части реализации, унаследованной от абстрактного класса, и отличаются лишь в части собственной реализации абстрактных методов родителя. Поэтому абстрактные классы применяются в случае построения иерархии однотипных, очень похожих друг на друга классов. В этом случае наследование от абстрактного класса, реализующего поведение объекта по умолчанию может быть полезно, так как позволяет избежать написания повторяющегося кода. Во всех остальных случаях лучше использовать интерфейсы.
#java #interface #abstractStringBuilder и StringBuffer
И StringBuilder, и StringBuffer используются для работы со строками, но между ними есть важные отличия.
StringBuilder:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello World{}
StringBuffer:
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Hello World{}
StringBuilder для лучшей производительности.
#java #stringbuilder #stringbufferdeepToString из класса Arrays используется для создания строкового представления многомерных массивов (например, массивов массивов). Он обходит каждый уровень вложенности массива и выводит его элементы в виде строки. Это удобно для работы с многомерными массивами, так как стандартный метод toString не раскрывает их структуру.
Пример использования:
int[][] array = {{1, 2, 3}, {4, 5, 6}};
System.out.println(Arrays.deepToString(array));
// [[1, 2, 3], [4, 5, 6]]
{}
Этот метод работает рекурсивно, обеспечивая полное отображение структуры массива любой вложенности.
#java #Arrays #deepToStringОтзывы канала
всего 11 отзывов
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
Java | Фишки и трюки — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 6.9K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 17.9, количество отзывов – 11, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 2237.76 ₽, а за 86 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий