Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
Varargs (Variable Arguments List, изменяющийся список аргументов) — это способ создания методов, которые могут принимать произвольное количество аргументов одного типа (от нуля и более). Данная возможность появилась в JDK 5.

Запись вида 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🔥21
⌨️ Diamond-оператор (<>) упрощает работу с обобщениями (Generics), позволяя компилятору автоматически выводить тип.

➡️ До Java 7 (без <>):

List<String> list = new ArrayList<String>(); // Приходилось дублировать <String>


➡️ С Java 7+ (с <>):

List<String> list = new ArrayList<>(); // Компилятор сам выводит <String>


Преимущества <>:
Уменьшает дублирование кода
Улучшает читаемость
Работает с любыми обобщёнными классами

Итог: Diamond-оператор делает код чище и проще, автоматизируя вывод типов!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141🔥1👀1
⌨️ Double-brace инициализация - техника создания и инициализации коллекций в одном выражении, используя анонимный внутренний класс.

Пример:


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. ☕️Java 8 Stream API:

List<String> planets = Stream.of("Mercury", "Venus", "Earth")
.collect(Collectors.toList());


2. ☕️Java 9+:
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
⌨️ Перегрузка (Overloading) vs. Переопределение (Overriding)

Перегрузка методов (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
👍141🔥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
👍141👎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
☕️ Apache PDFBox

🌐Apache PDFBox - это мощная библиотека с открытым исходным кодом для работы с PDF-документами в Java. Она позволяет создавать новые PDF-файлы, манипулировать существующими и извлекать содержимое из PDF-документов.

👁 Пример: Создание PDF с таблицей и изображением

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 {
// Метод для рисования таблицы (код опущен для краткости)
}
}

🛠Apache PDFBox предоставляет разработчикам гибкие инструменты для работы с PDF. Это делает его идеальным выбором для приложений, требующих создания отчетов, обработки форм или извлечения данных из PDF-документов.
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍103🌚1
⚡️ Как ускорить работу HashMap?

HashMap – одна из самых эффективных структур, но её можно ещё ускорить.

✔️ 3 способа оптимизации:

🟢Задавайте начальный размер – по умолчанию 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
👍191
☕️ Javassist

🌐Javassist - это мощная библиотека для манипуляции байткодом Java во время выполнения программы. Она позволяет динамически создавать и модифицировать классы и методы без необходимости перекомпиляции исходного кода.

💎Пример: Добавление логирования ко всем методам класса

import javassist.*;

public class LoggingExample {
public static void main(String[] args) throws Exception {
// Получаем пул классов
ClassPool pool = ClassPool.getDefault();

// Получаем класс, который хотим модифицировать
CtClass ctClass = pool.get("com.example.MyClass");

// Получаем все методы класса
CtMethod[] methods = ctClass.getDeclaredMethods();

for (CtMethod method : methods) {
// Добавляем логирование в начало каждого метода
method.insertBefore("System.out.println(\"Вызван метод: " + method.getName() + "\");");

// Добавляем логирование в конец каждого метода
method.insertAfter("System.out.println(\"Метод " + method.getName() + " завершен\");");
}

// Заменяем оригинальный класс модифицированным
ctClass.toClass();

// Теперь при использовании MyClass все его методы будут логироваться
// Например:
// MyClass obj = new MyClass();
// obj.someMethod();
}
}

🛠Javassist предоставляет мощные инструменты для метапрограммирования в Java. Это делает его незаменимым для разработки фреймворков, систем аспектно-ориентированного программирования и инструментов профилирования.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141
⌨️ Неочевидный момент: Переполнение при умножении Integer

В Java тип int (и его обёртка Integer) имеют фиксированный размер 32 бита. Если происходит переполнение (overflow), Java не выбрасывает ошибку, а просто "заворачивает" число.

✔️ Пример:


public class OverflowTest {
public static void main(String[] args) {
int max = Integer.MAX_VALUE; // 2147483647
int result = max * 2; // Переполнение!

System.out.println("Max: " + max); // Max: 2147483647
System.out.println("Result: " + result); // Result: -2
}
}


Почему? Потому что переполнение не вызывает ошибку — результат выходит за границу int и сбрасывается.

✔️ Что бы проверить переполнение используйте Math.multiplyExact():


public class SafeMultiply {
public static void main(String[] args) {
try {
int safeResult = Math.multiplyExact(Integer.MAX_VALUE, 2);
System.out.println(safeResult);
} catch (ArithmeticException e) {
System.out.println("Переполнение!");
}
}
}

Теперь при переполнении выбросится ArithmeticException.
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍3❤‍🔥1
☕️ Lambda - выражения

Одной из наиболее полезных фишек в Java, которая упрощает написание кода, является:

🔴Lambda-выражения.
Позволяют писать код более кратко и читаемо, особенно при работе с функциональными интерфейсами.

Что такое Lambda-выражения?

🖌Lambda-выраженияэто анонимные функции, которые могут принимать аргументы и возвращать значения. Они похожи на методы, но не имеют имени и могут быть определены прямо в теле метода. Это позволяет упростить код, удалив ненужную обертку.

📁 Пример использования Lambda-выражений


// Без Lambda
File directory = new File("./src/main/java");
String[] list = directory.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
});

// С Lambda
File directory = new File("./src/main/java");
String[] list = directory.list((dir, name) -> name.endsWith(".java"));


📈 Преимущества Lambda-выражений

1. 🔺Уменьшение количества кода: Lambda-выражения позволяют избежать создания анонимных классов, что делает код более лаконичным.

2. 🔺Улучшение читаемости: Код становится более понятным, так как основное внимание уделяется логике, а не обертке.

3.🔺 Упрощение работы с функциональными интерфейсами: Lambda-выражения идеально подходят для реализации функциональных интерфейсов, которые имеют только один абстрактный метод.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32
☕️Библиотека Java: AssertJ

💻AssertJ — это библиотека для написания fluent-assertions в тестах, которая предоставляет удобный и читаемый синтаксис для проверок. Основные возможности:


1. Богатый набор утверждений для всех стандартных типов
2. Поддержка коллекций, массивов, Optional, дат
3. Расширяемый API для кастомных проверок
4. Читаемый синтаксис с цепочкой вызовов

🗂Примеры :

// Проверки строк
assertThat("Hello Java")
.startsWith("Hello")
.endsWith("Java")
.hasSize(10)
.contains(" ");

// Проверки коллекций
assertThat(userList)
.hasSize(3)
.extracting(User::getName)
.containsExactly("Alice", "Bob", "Charlie");

// Проверки исключений
assertThatThrownBy(() -> service.process(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Parameter cannot be null");


🗂Расширенные возможности:

1.🗣 Для дат и времени:
assertThat(localDate)
.isAfter("2023-01-01")
.isBeforeOrEqualTo("2023-12-31");


2.🗣 Для Optional:
assertThat(optionalValue)
.isPresent()
.contains("expected");


3.🗣 Кастомные проверки:
assertThat(book)
.matches(b -> b.getPages() > 100, "толстая книга")
.matches(b -> b.getAuthor() != null, "имеет автора");


🟦Преимущества перед JUnit Assert:

1. 💬Более информативные сообщения об ошибках
2.
💬Поддержка цепочек проверок
3.
💬Встроенные проверки для коллекций
4.
💬Удобная работа с исключениями
5.
💬Поддержка Java 8+ features
Please open Telegram to view this post
VIEW IN TELEGRAM
👍223🔥1
☕️ JGraphT

🔄JGraphT - это мощная библиотека для работы с графами в Java. Она предоставляет широкий спектр алгоритмов и структур данных для решения задач, связанных с теорией графов.

✔️ Пример: Поиск кратчайшего пути в взвешенном графе

import org.jgrapht.Graph;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleWeightedGraph;

public class RoadNetworkExample {
public static void main(String[] args) {
// Создаем взвешенный граф
Graph roadNetwork =
new SimpleWeightedGraph<>(DefaultWeightedEdge.class);

// Добавляем города (вершины)
roadNetwork.addVertex("Москва");
roadNetwork.addVertex("Санкт-Петербург");
roadNetwork.addVertex("Нижний Новгород");
roadNetwork.addVertex("Казань");

// Добавляем дороги (ребра) с расстояниями
roadNetwork.setEdgeWeight(roadNetwork.addEdge("Москва", "Санкт-Петербург"), 700);
roadNetwork.setEdgeWeight(roadNetwork.addEdge("Москва", "Нижний Новгород"), 400);
roadNetwork.setEdgeWeight(roadNetwork.addEdge("Нижний Новгород", "Казань"), 400);
roadNetwork.setEdgeWeight(roadNetwork.addEdge("Санкт-Петербург", "Казань"), 1500);

// Находим кратчайший путь
DijkstraShortestPath dijkstraAlg =
new DijkstraShortestPath<>(roadNetwork);
var path = dijkstraAlg.getPath("Москва", "Казань");

System.out.println("Кратчайший путь: " + path.getVertexList());
System.out.println("Общее расстояние: " + path.getWeight() + " км");
}
}

🛠JGraphT предоставляет мощные инструменты для работы с графами, что делает его незаменимым для решения задач оптимизации, анализа сетей и многих других областей, где применяется теория графов.
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍61
☕️Фишка Java: Optional для Null-Safety

⚙️Работа с null-значениями традиционно была источником ошибок в Java. Класс Optional предоставляет более элегантный способ обработки потенциально отсутствующих значений.


💬Традиционный подход:


User user = getUserById(id);
if (user != null) {
Address address = user.getAddress();
if (address != null) {
String city = address.getCity();
if (city != null) {
System.out.println(city.toUpperCase());
}
}
}


💻С использованием Optional:


Optional.ofNullable(getUserById(id))
.map(User::getAddress)
.map(Address::getCity)
.ifPresent(city -> System.out.println(city.toUpperCase()));


💻Основные методы Optional:

1. ofNullable() - создает Optional из значения, которое может быть null
2. map() - преобразует значение, если оно присутствует
3. orElse() - предоставляет значение по умолчанию
4. ifPresent() - выполняет действие, если значение есть
5. orElseThrow() - бросает исключение, если значения нет


🗂Примеры:

1.🔐 Безопасное получение вложенных свойств:


String cityName = Optional.ofNullable(order)
.map(Order::getCustomer)
.map(Customer::getAddress)
.map(Address::getCity)
.orElse("Unknown");


2. 🗂Комбинация нескольких Optional:


Optional<Double> totalPrice = Optional.ofNullable(order1)
.flatMap(o1 -> Optional.ofNullable(order2)
.map(o2 -> o1.getPrice() + o2.getPrice()));


3.
🗂Работа с коллекциями:


List<String> names = Optional.ofNullable(userList)
.orElse(Collections.emptyList())
.stream()
.map(User::getName)
.filter(Objects::nonNull)
.collect(Collectors.toList());


🗂Преимущества использования Optional:

1. Явное указание на возможность отсутствия значения
2. Устранение проверок на null в коде
3. Четкая цепочка преобразований
4. Более читаемый и выразительный код
Please open Telegram to view this post
VIEW IN TELEGRAM
👍142
☕️Лямбда-выражения и Stream API

💻Лямбда-выражения и Stream API кардинально изменили подход к обработке данных в Java, позволив писать более декларативный и выразительный код.


🗂Пример без лямбд:


List<String> names = Arrays.asList("John", "Alice", "Bob");
Collections.sort(names, new Comparator() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});


🗂С лямбда-выражением:


List<String> names = Arrays.asList("John", "Alice", "Bob");
names.sort((a, b) -> a.compareTo(b));


🔵Stream API позволяет выполнять сложные операции над коллекциями:


List<String> filteredNames = names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());


🗂Ключевые преимущества:

1. Упрощение работы с коллекциями
2. Возможность цепочечных вызовов методов
3. Параллельная обработка через parallelStream()
4. Ленивое выполнение операций


🗂Примеры:

1.🔅 Фильтрация и преобразование:


List<Product> expensiveProducts = products.stream()
.filter(p -> p.getPrice() > 1000)
.map(p -> p.withDiscount(0.1))
.collect(Collectors.toList());


2.🟡 Группировка данных:


Map<String, List<Employ>> employeesByDepartment = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));


3.💬 Статистические операции:


IntSummaryStatistics stats = salaries.stream()
.mapToInt(Integer::intValue)
.summaryStatistics();


🗂Особенности работы:

- 💬Stream не изменяет исходную коллекцию
- 💬Многие операции возвращают новый Stream
- 💬Терминальные операции завершают цепочку
- 💬Оптимизированная работа с памятью
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥42
☕️Библиотека Java: MapStruct

🗂MapStruct это генератор кода для маппинга между Java-бинами, который создает реализации mapper-ов на этапе компиляции.


🗂Основные преимущества:

1. 🗣Автоматический маппинг полей с одинаковыми именами
2. 🗣Высокая производительность (нет рефлексии в runtime)
3. 🗣Поддержка сложных преобразований
4. 🗣Интеграция с Spring и CDI


🗂Пример использования:

@Mapper(componentModel = "spring")
public interface UserMapper {

@Mapping(target = "fullName", expression = "java(user.getFirstName() + \" \" + user.getLastName())")
@Mapping(target = "status", constant = "ACTIVE")
UserDto toDto(User user);

@Mapping(target = "firstName", source = "fullName.split(\" \")[0]")
@Mapping(target = "lastName", source = "fullName.split(\" \")[1]")
User toEntity(UserDto dto);
}


🗂Ключевые особенности:

-💬 Генерация чистого Java-кода без зависимостей
-💬 Поддержка коллекций и потоков
-💬 Преобразование типов
-💬 Работа с вложенными объектами
-💬 Кастомные методы маппинга


🗣Интеграция с Spring:

@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;

public UserDto createUser(UserRequest request) {
User user = userMapper.toEntity(request);
// бизнес-логика
return userMapper.toDto(user);
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍3🔥3
☕️ Quartz

Quartz - это мощная библиотека с открытым исходным кодом для планирования и выполнения задач по расписанию в Java-приложениях. Она предоставляет гибкие возможности для определения сложных расписаний выполнения задач и поддерживает кластеризацию.

🌐Пример: Планирование задачи резервного копирования базы данных

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.time.LocalDateTime;

public class BackupSchedulerExample {
public static void main(String[] args) throws SchedulerException {
// Создаем планировщик
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

// Определяем задачу
JobDetail job = JobBuilder.newJob(DatabaseBackupJob.class)
.withIdentity("databaseBackupJob", "backupGroup")
.build();

// Создаем триггер для запуска задачи каждый день в 2:00
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("dailyBackupTrigger", "backupGroup")
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(2, 0))
.build();

// Планируем задачу с триггером
scheduler.scheduleJob(job, trigger);

// Запускаем планировщик
scheduler.start();

System.out.println("Планировщик резервного копирования запущен.");
System.out.println("Следующее резервное копирование запланировано на: "
+ trigger.getNextFireTime());

// Оставляем планировщик работать
try {
Thread.sleep(60000); // Ждем 1 минуту для демонстрации
} catch (InterruptedException e) {
e.printStackTrace();
}

// Останавливаем планировщик
scheduler.shutdown();
}

// Класс, представляющий задачу резервного копирования
public static class DatabaseBackupJob implements Job {
@Override
public void execute(JobExecutionContext context) {
System.out.println("Выполняется резервное копирование базы данных: "
+ LocalDateTime.now());
// Здесь был бы реальный код для резервного копирования
}
}
}

🔐Quartz предоставляет надежное решение для планирования и выполнения задач в Java-приложениях. Его гибкость позволяет реализовывать сложные сценарии планирования, от простых периодических задач до сложных расписаний с учетом праздников, временных зон и других факторов.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍6🔥1🗿1
⌨️ Pattern Matching для instanceof

Начиная с Java 16, проверка типов с помощью instanceof стала гораздо удобнее благодаря Pattern Matching. Раньше, после проверки объекта на принадлежность к определённому классу, нужно было выполнять явное приведение типа. Теперь это можно сделать в одной строке.

Пример до Java 16:

if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}


Пример с Pattern Matching:

if (obj instanceof String str) {
System.out.println(str.length());
}


Теперь после instanceof можно сразу же использовать объект нужного типа в коде, что делает программу более читабельной и компактной.

#java #PatternMatching #instanceof
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥31
☕️ JBCrypt

🔺JBCrypt - это библиотека для безопасного хеширования паролей в Java, реализующая алгоритм bcrypt. Она обеспечивает надежную защиту паролей от атак перебором и радужных таблиц.

💫 Пример: Система регистрации и аутентификации

import org.mindrot.jbcrypt.BCrypt;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class AuthenticationSystem {
private static Map users = new HashMap<>();

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

while (true) {
System.out.println("1. Регистрация");
System.out.println("2. Вход");
System.out.println("3. Выход");
System.out.print("Выберите действие: ");

int choice = scanner.nextInt();
scanner.nextLine(); // Очистка буфера

switch (choice) {
case 1:
register(scanner);
break;
case 2:
login(scanner);
break;
case 3:
System.out.println("До свидания!");
return;
default:
System.out.println("Неверный выбор. Попробуйте снова.");
}
}
}

private static void register(Scanner scanner) {
System.out.print("Введите имя пользователя: ");
String username = scanner.nextLine();
System.out.print("Введите пароль: ");
String password = scanner.nextLine();

String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
users.put(username, hashedPassword);

System.out.println("Регистрация успешна!");
}

private static void login(Scanner scanner) {
System.out.print("Введите имя пользователя: ");
String username = scanner.nextLine();
System.out.print("Введите пароль: ");
String password = scanner.nextLine();

if (users.containsKey(username) && BCrypt.checkpw(password, users.get(username))) {
System.out.println("Вход выполнен успешно!");
} else {
System.out.println("Неверное имя пользователя или пароль.");
}
}
}

🛡JBCrypt предоставляет простой и эффективный способ защиты паролей пользователей. Использование этой библиотеки значительно повышает безопасность приложений, работающих с аутентификацией пользователей.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102🥰1
⌨️ Лямбда-выражения и свой кастомный функциональный интерфейс

Для того что бы определить лямбда-выражение, нам нужен функциональный интерфейс. Изобретём свой:

@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}

Функциональный интерфейс MathOperation содержит один абстрактный метод operate, который принимает два значения типа int и возвращает int. Аннотация @FunctionalInterface указывает на то, что интерфейс предназначен для использования в функциональном программировании и должен содержать только один абстрактный метод. Но аннотация не обязательна.

Использование лямбда-выражения:

public class LambdaExample {
public static void main(String[] args) {
// Реализация интерфейса с помощью лямбда-выражения
MathOperation addition = (a, b) -> a + b;
MathOperation subtraction = (a, b) -> a - b;
MathOperation multiplication = (a, b) -> a * b;
MathOperation division = (a, b) -> a / b;

int x = 10;
int y = 5;

System.out.println("Addition: " + operate(x, y, addition)); // 15
System.out.println("Subtraction: " + operate(x, y, subtraction)); // 5
System.out.println("Multiplication: " + operate(x, y, multiplication)); // 50
System.out.println("Division: " + operate(x, y, division)); // 2
}

// Метод, принимающий MathOperation и применяющий его к данным
private static int operate(int a, int b, MathOperation operation) {
return operation.operate(a, b);
}
}


В нашем примере лямбда-выражения используются для создания экземпляров интерфейса MathOperation для выполнения различных математических операций (сложение, вычитание и т.д.).

Метод operate принимает два целых числа и функциональный интерфейс MathOperation, затем выполняет переданную операцию. В метод в третьем параметре можно передать непосредственно лямбда-выражение, не используя промежуточную переменную.

#java #lambda #FunctionalInterface
Please open Telegram to view this post
VIEW IN TELEGRAM
👍123