Pascal4eg / Java

 Java | Фишки и трюки

Stream

Все операции Stream делятся на промежуточные и терминальные и объединяются в потоковые конвейеры.

Потоковый конвейер состоит из источника (например, коллекции, массива, функции-генератора, канала ввода-вывода или генератора бесконечной последовательности) за которым следует ноль или более промежуточных операций и терминальной операции.

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

Они составляют конвейер выполнения Stream. Промежуточную операцию можно добавить в конвейер Stream методами:
filter()
map()
flatMap()
distinct()
sorted()
peek()
limit()
skip()

Читать дальше

Защита от повторного запроса с помощью БД

Если вы разрабатываете Веб-приложение или REST-сервис, то рано или поздно столкнётесь с повторными запросами. Что имеется в виду? Объясню на примере Веб-страницы с кнопкой. По нажатию на кнопку, на бэкенд отправляется запрос. Запрос, соответственно, синхронный и пока серверная часть делает какую-то работу, браузер клиента показывает, что загружает страницу. Если это происходит продолжительное время, клиент может подумать, что его запрос завис и нажать кнопку ещё раз. Также повторное нажатие может произойти случайно.

Какая тут может произойти проблема? Если это, например, какой-то запрос данных, то в общем-то проблемы и нет, но если это действие, которое должно отработать только один раз, то тут могут быть весьма неприятные последствия. Для примера в интернет-магазине собрана корзина и создан заказ на оплату (статус REGISTERED), далее по нажатию кнопки "оплатить" с клиента списывают деньги и переводят заказ в статус оплачен (PAID). И если в этом процессе произойдёт двойной запрос, то с клиента могут списать деньги за заказ два раза.

Читать статью

Читать дальше

Комбинирование предикатов

List<String> fruits = List.of("apple", "orange", "pineapple", "grapefruit", "melon");
Predicate<String> isEqualsOrange = Predicate.isEqual("orange");
Predicate<String> isEqualsGrapefruit = Predicate.isEqual("grapefruit");
Predicate<String> isEqualsCitrus = isEqualsOrange.or(isEqualsGrapefruit);
Predicate<String> isNotEqualsCitrus = isEqualsCitrus.negate();

fruits.stream().filter(isEqualsOrange).forEach(System.out::println);
// orange

fruits.stream().filter(isEqualsCitrus).forEach(System.out::println);
// orange grapefruit

fruits.stream().filter(isNotEqualsCitrus).forEach(System.out::println);
// apple pineapple melon

🧩 Predicate - встроенный функциональный интерфейс, добавленный в Java 8 в пакет java.util.function.

Читать дальше

Запись (record)

public record Point (int x, int y) { }

public static void main(String[] args) {
    Point point = new Point(100, 100);
    System.out.println(point);
}
// Point[x=100, y=100]

📝 Запись (record) — это класс, объявленный с ключевым словом record вместо ключевого слова class. Запись служит контейнером неизменяемых данных и предназначена для лаконичного описания DTO (Data Transfer Object).

Читать дальше

Sentry for Java

Sentry for Java — это программный инструмент, призванный помочь разработчикам отслеживать и управлять ошибками, исключениями и сбоями в приложениях Java.

Читать дальше

Double braces инициализация

// Double braces initialization
List<String> planets = new ArrayList<>() {{
    add("Mercury");
    add("Venus"); 
    add("Earth"); 
    add("Mars");
    add("Jupiter");
    add("Saturn"); 
    add("Uranus"); 
    add("Neptune");
}};

Double braces инициализация - это создание и инициализация объекта в одном java выражении. Чаще всего используется с коллекциями.

На самом деле в этот момент происходит создание анонимного внутреннего класса, расширяющего ArrayList и определение в нём блока инициализации экземпляра.

Читать дальше

Stream API

Stream API появился в Java 8 и существенно упростил работу с коллекциями. Теперь можно писать короче и красивее фильтрацию, сортировку и обработку данных.

private final List<Property> properties = getProperties();

/**
 * Поиск свойства по имени в списке
 * @param propName наименование свойства
 * @return найденное свойство или null если не найдено
 */
public Property getPropertyByName(String propName) {
    return properties.stream().filter(p -> p.getName().equals(propName)).findFirst().orElse(null);
}
Читать дальше

Пожалуй самый распространенный способ избежания Null Pointer Exception

Часто можно получить NPE при проверке на равенство переменной и константы. Дело в том, что переменная может содержать null и при вызове метода equals у такой переменной, мы получим исключение NullPointerException.

Читать дальше