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.
Читать дальше