📌 Для чего нужен
StructuredTaskScope?StructuredTaskScopeFuture, CompletableFuture и ExecutorService.
import java.util.concurrent.*;
public class StructuredTaskScopeExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Запускаем две параллельные задачи
var task1 = scope.fork(() -> fetchDataFromAPI("API 1"));
var task2 = scope.fork(() -> fetchDataFromAPI("API 2"));
// Дожидаемся завершения (или отмены в случае ошибки)
scope.join();
scope.throwIfFailed(); // Выбросит исключение, если одна из задач завершилась с ошибкой
// Получаем результаты
String result1 = task1.get();
String result2 = task2.get();
System.out.println("Result 1: " + result1);
System.out.println("Result 2: " + result2);
}
}
private static String fetchDataFromAPI(String apiName) throws InterruptedException {
Thread.sleep(1000); // Имитация задержки запроса
if (Math.random() > 0.8) throw new RuntimeException(apiName + " failed!"); // Имитация ошибки
return apiName + " response";
}
}
#java #concurrency #structuredconcurrency
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
В Java 17 появился ZGC – он обещает минимальную задержку. Но лучше ли он G1GC?
+------+----------+-----------+----------+
| GC | Паузы | Поддержка | CPU |
| | | хипа | нагрузка |
+------+----------+-----------+----------+
| G1GC | До 200ms | До 16ТБ | Средняя |
| ZGC | <10ms | До 16ТБ | Низкая |
+------+----------+-----------+----------+
-XX:+UseZGC
#java #gc #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
Модификатор
final может применяться к переменным, параметрам методов, полям и методам класса или самим классам.✔️ Класс не может иметь наследников;
✔️ Метод не может быть переопределен в классах наследниках;
✔️ Поле не может изменить свое значение после инициализации;
✔️ Параметры методов не могут изменять своё значение внутри метода;
✔️ Локальные переменные не могут быть изменены после присвоения им значения.
#java #final
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2🔥1
Работа с JSON – частая задача, но Jackson, Gson и JSON-B работают по-разному. Какой выбрать?
• Jackson – самый быстрый (использует ByteBuffer).• Gson – медленнее, так как использует Reflection.• JSON-B – стандартный API, но проигрывает по производительности.
ObjectMapper objectMapper = new ObjectMapper();
// Объект → JSON (сериализация)
Person person = new Person("Alice", 30);
String json = objectMapper.writeValueAsString(person);
System.out.println("Jackson Serialized: " + json);
// JSON → Объект (десериализация)
Person deserialized = objectMapper.readValue(json, Person.class);
System.out.println("Jackson Deserialized: " + deserialized.name + ", " + deserialized.age);
Gson gson = new Gson();
// Объект → JSON (сериализация)
Person person = new Person("Bob", 25);
String json = gson.toJson(person);
System.out.println("Gson Serialized: " + json);
// JSON → Объект (десериализация)
Person deserialized = gson.fromJson(json, Person.class);
System.out.println("Gson Deserialized: " + deserialized.name + ", " + deserialized.age);
Jsonb jsonb = JsonbBuilder.create();
// Объект → JSON (сериализация)
Person person = new Person("Charlie", 35);
String json = jsonb.toJson(person);
System.out.println("JSON-B Serialized: " + json);
// JSON → Объект (десериализация)
Person deserialized = jsonb.fromJson(json, Person.class);
System.out.println("JSON-B Deserialized: " + deserialized.name + ", " + deserialized.age);
#java #json #jackson #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤3🔥3🤔1
❇️Инлайн-классы (или value-классы) представляют собой ключевую часть проекта Valhalla, который значительно изменяет подход к организации данных в Java. Основная идея заключается в объединении производительности примитивов с гибкостью объектов, что позволяет создавать легковесные структуры данных без накладных расходов на размещение в куче.
1.
2.
3.
Пример использования инлайн-класса:
Рассмотрим класс Point,который представляет координаты на плоскости:
public primitive class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Ключевое слово
1.
2.
3.
Пример работы с массивом:
Point[] points = new Point[100];
for (int i = 0; i < points.length; i++) {
points[i] = new Point(i, i * 2);
}
System.out.println(points[50].getX()); // 50
В данном случае массив points занимает меньше памяти и обрабатывается быстрее по сравнению с обычными объектами.
1.
2.
3.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥4❤1
Records, введенные в Java 14, предоставляют лаконичный способ создания неизменяемых классов данных. Sealed classes, появившиеся в Java 17, позволяют ограничивать наследование.
public sealed interface PaymentMethod permits CreditCard, BankTransfer, PayPal {
boolean isValid();
void process();
}
public record CreditCard(String cardNumber, String expiryDate, String cvv) implements PaymentMethod {
@Override
public boolean isValid() {
return cardNumber != null && cardNumber.length() == 16
&& expiryDate != null && cvv != null;
}
@Override
public void process() {
System.out.println("Processing credit card payment");
}
}
public record BankTransfer(String accountNumber, String bankCode) implements PaymentMethod {
@Override
public boolean isValid() {
return accountNumber != null && bankCode != null;
}
@Override
public void process() {
System.out.println("Processing bank transfer");
}
}
public record PayPal(String email) implements PaymentMethod {
@Override
public boolean isValid() {
return email != null && email.contains("@");
}
@Override
public void process() {
System.out.println("Processing PayPal payment");
}
}
public record Payment(UUID id, BigDecimal amount, PaymentMethod method) {
public boolean processPayment() {
if (method.isValid()) {
method.process();
return true;
}
return false;
}
}
1. Типобезопасность: Компилятор гарантирует, что только определенные классы могут реализовывать PaymentMethod.
2. Неизменяемость: Records обеспечивают неизменяемость данных.
3. Краткость кода: Records автоматически генерируют методы.
Пример использования:
public void handlePayment(Payment payment) {
if (payment.processPayment()) {
switch (payment.method()) {
case CreditCard cc -> handleCreditCardPayment(cc);
case BankTransfer bt -> handleBankTransferPayment(bt);
case PayPal pp -> handlePayPalPayment(pp);
}
} else {
handleFailedPayment(payment);
}
}
Этот подход особенно полезен для моделирования бизнес-доменов и реализации паттерна "Состояние".
Он позволяет создавать более безопасный и поддерживаемый код.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10❤🔥2
1.
2.
3.
public class StackWalkerExample {
public static void main(String[] args) {
method1();
}
private static void method1() {
method2();
}
private static void method2() {
method3();
}
private static void method3() {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
walker.forEach(frame -> {
System.out.println("Класс: " + frame.getClassName() +
", Метод: " + frame.getMethodName() +
", Строка: " + frame.getLineNumber());
});
}
}
Более сложный пример с фильтрацией и обработкой стека:
public class AdvancedStackWalkerExample {
public static void main(String[] args) {
logMethodCall();
}
private static void logMethodCall() {
StackWalker walker = StackWalker.getInstance(EnumSet.of(
StackWalker.Option.RETAIN_CLASS_REFERENCE,
StackWalker.Option.SHOW_REFLECT_FRAMES
));
List callStack = walker.walk(stream ->
stream.filter(frame -> !frame.getClassName().startsWith("java.lang"))
.map(frame -> frame.getClassName() + "." + frame.getMethodName())
.limit(5)
.collect(Collectors.toList())
);
System.out.println("Стек вызовов (до 5 методов, исключая java.lang):");
callStack.forEach(System.out::println);
}
}
В заключение, StackWalker предоставляет мощный и эффективный способ работы со стеком вызовов, улучшая производительность и гибкость кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1
Процесс — экземпляр программы во время выполнения, независимый объект, которому выделены системные ресурсы (например, процессорное время и память). Каждый процесс выполняется в отдельном адресном пространстве: один процесс не может получить доступ к переменным и структурам данных другого. Если процесс хочет получить доступ к чужим ресурсам, необходимо использовать межпроцессное взаимодействие. Это могут быть конвейеры, файлы, каналы связи между компьютерами и многое другое.
Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.
Поток(thread) — определенный способ выполнения процесса, определяющий последовательность исполнения кода в процессе. Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах. Потоки могут исполнять один и тот же код и манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах. Так как потоки расходуют существенно меньше ресурсов, чем процессы, в процессе выполнения работы выгоднее создавать дополнительные потоки и избегать создания новых процессов.
#java #process #thread
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤3🔥2
Есть несколько преимуществ в неизменности строк:
✔️ Пул строк возможен только потому, что строка неизменяемая, таким образом виртуальная машина сохраняет больше свободного места в Heap, поскольку разные строковые переменные указывают на одну и ту же переменную в пуле. Если бы строка была изменяемой, то интернирование строк не было бы возможным, потому что изменение значения одной переменной отразилось бы также и на остальных переменных, ссылающихся на эту строку.
✔️ Если строка будет изменяемой, тогда это станет серьезной угрозой безопасности приложения. Например, имя пользователя базы данных и пароль передаются строкой для получения соединения с базой данных и в программировании сокетов реквизиты хоста и порта передаются строкой. Так как строка неизменяемая, её значение не может быть изменено, в противном случае злоумышленник может изменить значение ссылки и вызвать проблемы в безопасности приложения.
✔️ Неизменяемость позволяет избежать синхронизации: строки безопасны для многопоточности и один экземпляр строки может быть совместно использован различными потоками.
✔️ Строки используются classloader и неизменность обеспечивает правильность загрузки класса.
✔️ Поскольку строка неизменяемая, её hashCode() кэшируется в момент создания и нет необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в HashMap т.к. его обработка происходит быстрее.
#java #string #immutable
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍6
nullВозвращение пустых коллекций вместо
null-это рекомендуемый подход для методов, возвращающих коллекции. Он упрощает обработку данных, предотвращает ошибки и делает код более предсказуемым.1. Улучшение читаемости: Код становится проще, так как не нужно проверять результат на null.
2. Предотвращение NullPointerException: Исключается вероятность ошибок, связанных с доступом к null.
3.Соответствие принципу наименьшего удивления: Методы всегда возвращают коллекцию, даже если она пуста.
4. Эффективность: Пустые коллекции создаются один раз и переиспользуются благодаря реализации через паттерн Singleton.
5. Совместимость с функциональным программированием: Пустые коллекции легко интегрируются в стримы и другие функциональные конструкции.
Пример:
public class CacheService {
private final Map<String, List<Object>> cache = new ConcurrentHashMap<>();
public List<Object> getCachedValues(String key) {
return cache.getOrDefault(key, Collections.emptyList());
}
public void addToCache(String key, Object value) {
cache.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}
}
Использование пустых коллекций вместо null делает код более устойчивым и предсказуемым. Это особенно важно в сложных многопоточных приложениях или системах с большим количеством взаимосвязанных компонентов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤3
Varargs (Variable Arguments List, изменяющийся список аргументов) — это способ создания методов, которые могут принимать произвольное количество аргументов одного типа (от нуля и более). Данная возможность появилась в JDK 5.
Запись вида
При этом три точки после типа указывают, что метод в качестве аргумента может принимать как массив, так и любую последовательность аргументов, записанных через запятую, которая все равно преобразуется в одномерный массив - «под капотом» компилятор на уровне байт-кода неявно заменяет переданную последовательность массивом. Уже в методе аргумент varargs используется как одномерный массив.
Альтернативой varargs является перегрузка методов или передача в метод массива значений.
Varargs был создан с целью упрощения работы программиста, удобства и краткости кода.
📌 В качестве ограничения любой метод может использовать varargs только в единственном числе и строго последним аргументом.
Запись вида
Object... args и есть varargs. При этом три точки после типа указывают, что метод в качестве аргумента может принимать как массив, так и любую последовательность аргументов, записанных через запятую, которая все равно преобразуется в одномерный массив - «под капотом» компилятор на уровне байт-кода неявно заменяет переданную последовательность массивом. Уже в методе аргумент varargs используется как одномерный массив.
Альтернативой varargs является перегрузка методов или передача в метод массива значений.
Varargs был создан с целью упрощения работы программиста, удобства и краткости кода.
📌 В качестве ограничения любой метод может использовать varargs только в единственном числе и строго последним аргументом.
🔥8👍5
null? null не имеет хеш-кода, потому что null не является объектом. Однако, при использовании null в структурах данных, таких как HashMap или HashSet, применяется специальная логика:null в HashMap и HashSet?✔️ В
HashMap ключ null всегда попадает в первый бакет (bucket 0).✔️ В
HashSet (который использует HashMap внутри) null также хранится в этом же бакете.✔️ Проверки выполняются в
Objects.hashCode(), который для null всегда возвращает 0.
System.out.println(Objects.hashCode(null)); // 0
📌 Вывод:
null не имеет собственного хеш-кода, но в хеш-структурах ему назначается 0.Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥2❤1
<>) упрощает работу с обобщениями (Generics), позволяя компилятору автоматически выводить тип.<>):
List<String> list = new ArrayList<String>(); // Приходилось дублировать <String>
<>):
List<String> list = new ArrayList<>(); // Компилятор сам выводит <String>
Преимущества
<>:✅ Уменьшает дублирование кода
✅ Улучшает читаемость
✅ Работает с любыми обобщёнными классами
⚡ Итог: Diamond-оператор делает код чище и проще, автоматизируя вывод типов!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1🔥1👀1
List<String > planets = new ArrayList<>() {{
add ("Mercury");
add ("Venus");
add ("Earth");
add ("Mars");
add ("Jupiter");
add ("Saturn");
add ("Uranus") ;
add ("Neptune");
}};
1. Краткость
2. Читаемость
3. Удобство для небольших коллекций
1. Создание анонимного класса (увеличение потребления памяти)
2. Скрытая ссылка (возможные утечки памяти)
3. Ограничения с final классами
4. Несовместимость с оператором diamond
5. Потенциальное влияние на производительность
6. Считается антипаттерном
1.
List<String> planets = Stream.of("Mercury", "Venus", "Earth")
.collect(Collectors.toList());
2.
List<String> planets = List.of("Mercury", "Venus", "Earth");3.🖨Конструктор копирования:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Несмотря на удобство, double-brace инициализация считается антипаттерном из-за проблем с производительностью и возможных утечек памяти.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥1🌭1
Перегрузка методов (Method Overloading) – это создание нескольких методов с одним именем, но разными параметрами (различаются количество или типы аргументов).
Пример:
class MathUtils {
int sum(int a, int b) {
return a + b;
}
double sum(double a, double b) { // Перегруженный метод
return a + b;
}
}
Переопределение методов (Method Overriding) – это изменение поведения унаследованного метода в подклассе.
Пример:
class Animal {
void sound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
void sound() { // Переопределение метода
System.out.println("Bark");
}
}
⚡ Вывод:
✔️Перегрузка – это создание нескольких версий метода в одном классе.
✔️Переопределение – это изменение поведения метода родителя в подклассе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1🔥1
Array vs ArrayListВыбор между
Array и ArrayList зависит от специфики задачи, которую требуется решить. 📌Помните о следующих особенностях этих типов:
✔️
Array имеет фиксированный размер и память для него выделяется в момент объявления, а размер ArrayLists может динамически изменяться.✔️ Массивы работают гораздо быстрее, а в
ArrayList намного проще добавлять/удалять элементы.✔️ При работе с
Array велика вероятность получить ошибку ArrayIndexOutOfBoundsException.
✔️ У
ArrayList только одно измерение, а вот массивы могут быть многомерными.
import java.util.ArrayList;
public class arrayVsArrayList {
public static void main(String[] args) {
// объявление Array
int[] myArray = new int[6];
// обращение к несуществующему индексу
myArray[7]= 10; // ArrayIndexOutOfBoundsException
// объявление ArrayList
ArrayList<Integer> myArrayList = new ArrayList<>();
// простое добавление и удаление элементов
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(4);
myArrayList.add(5);
myArrayList.remove(0);
// получение элементов ArrayList
for(int i = 0; i < myArrayList.size(); i++) {
System.out.println("Element: " + myArrayList.get(i));
}
// многомерный Array
int[][][] multiArray = new int [3][3][3];
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1👎1
ArrayList vs LinkedListОба класса реализуют
List, но имеют разные внутренние структуры и производительность.ArrayList использует динамический массив, а LinkedList использует двусвязный список.✔️ Используйте
ArrayList, если важен быстрый доступ по индексу и добавление в конец.✔️ Используйте
LinkedList, если часто удаляете/вставляете элементы в середину.📌
ArrayList чаще предпочтительнее, так как LinkedList требует больше памяти и редко даёт преимущества. 🚀Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🔥3👍2🤔2
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.io.IOException;
public class PDFCreationExample {
public static void main(String[] args) throws IOException {
try (PDDocument document = new PDDocument()) {
PDPage page = new PDPage();
document.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
// Добавляем заголовок
contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 16);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Отчет о продажах");
contentStream.endText();
// Добавляем таблицу
drawTable(contentStream, 50, 700, new String[][] {
{"Продукт", "Количество", "Цена"},
{"Яблоки", "100", "50"},
{"Бананы", "150", "40"},
{"Апельсины", "75", "60"}
});
// Добавляем изображение
PDImageXObject image = PDImageXObject.createFromFile("path/to/image.jpg", document);
contentStream.drawImage(image, 50, 500, 200, 150);
}
document.save("Отчет_о_продажах.pdf");
}
}
private static void drawTable(PDPageContentStream contentStream, float x, float y, String[][] content) throws IOException {
// Метод для рисования таблицы (код опущен для краткости)
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍10❤3🌚1
HashMap?HashMap – одна из самых эффективных структур, но её можно ещё ускорить.HashMap увеличивается при заполнении на 75%, что может приводить к перераспределению. Укажите new HashMap<>(1000) для больших данных.computeIfAbsent() – сокращает проверку наличия ключа перед вставкой.synchronized HashMap – вместо этого применяйте ConcurrentHashMap.Map<String, Integer> map = new HashMap<>(1000);
map.computeIfAbsent("key", k -> 42);
HashMap под свои задачи, особенно если храните большие объёмы данных.#java #hashmap #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤1