Перейти к основному содержимому

Необязательные дополнения API Java 9

· 4 мин. чтения

Задача: Наибольшая подстрока палиндром

Для заданной строки s, верните наибольшую подстроку палиндром входящую в s. Подстрока — это непрерывная непустая последовательность символов внутри строки. Стока является палиндромом, если она читается одинаково в обоих направлениях...

ANDROMEDA 42

1. Обзор

В этой статье мы рассмотрим дополнения Java 9 к необязательному API.

Помимо модульности, в Java 9 также добавлены три очень полезных метода для класса Optional .

2. Метод or ()

Иногда, когда наш необязательный элемент пуст, мы хотим выполнить какое-то другое действие, которое также возвращает необязательный элемент.

До версии Java 9 класс Optional имел только методы orElse() и orElseGet() , но оба должны возвращать развернутые значения.

В Java 9 представлен метод or() , который лениво возвращает еще один необязательный элемент, если наш необязательный элемент пуст. Если наш первый необязательный параметр имеет определенное значение, лямбда, переданная методу or() , не будет вызываться, а значение не будет вычислено и возвращено:

@Test
public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
//given
String expected = "properValue";
Optional<String> value = Optional.of(expected);
Optional<String> defaultValue = Optional.of("default");

//when
Optional<String> result = value.or(() -> defaultValue);

//then
assertThat(result.get()).isEqualTo(expected);
}

Если необязательный параметр пуст , возвращаемый результат будет таким же, как и значение по умолчанию:

@Test
public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
// given
String defaultString = "default";
Optional<String> value = Optional.empty();
Optional<String> defaultValue = Optional.of(defaultString);

// when
Optional<String> result = value.or(() -> defaultValue);

// then
assertThat(result.get()).isEqualTo(defaultString);
}

3. Метод ifPresentOrElse ()

Когда у нас есть необязательный экземпляр, часто мы хотим выполнить определенное действие над его базовым значением. С другой стороны, если необязательный элемент пуст , мы хотим зарегистрировать его или отследить этот факт, увеличив некоторую метрику.

Именно для таких случаев и создан метод ifPresentOrElse() . Мы можем передать Consumer , который будет вызываться, если опционально определено, и Runnable , который будет выполняться, если опцион пуст.

Допустим, у нас есть определенный необязательный параметр, и мы хотим увеличить определенный счетчик, если значение присутствует:

@Test
public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
// given
Optional<String> value = Optional.of("properValue");
AtomicInteger successCounter = new AtomicInteger(0);
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

// when
value.ifPresentOrElse(
v -> successCounter.incrementAndGet(),
onEmptyOptionalCounter::incrementAndGet);

// then
assertThat(successCounter.get()).isEqualTo(1);
assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
}

Обратите внимание, что обратный вызов, переданный в качестве второго аргумента, не был выполнен.

В случае пустого опциона выполняется второй обратный вызов:

@Test
public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
// given
Optional<String> value = Optional.empty();
AtomicInteger successCounter = new AtomicInteger(0);
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

// when
value.ifPresentOrElse(
v -> successCounter.incrementAndGet(),
onEmptyOptionalCounter::incrementAndGet);

// then
assertThat(successCounter.get()).isEqualTo(0);
assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
}

4. Метод stream ()

Последний метод, добавленный в класс Optional в Java 9, — это метод stream() .

Java имеет очень плавный и элегантный Stream API, который может работать с коллекциями и использует множество концепций функционального программирования. В новейшей версии Java представлен метод stream() в классе Optional , который позволяет нам рассматривать экземпляр Optional как поток.

Допустим, у нас есть определенный необязательный параметр, и мы вызываем для него метод stream() . Это создаст Stream из одного элемента, на котором мы сможем использовать все методы, доступные в Stream API :

@Test
public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
// given
Optional<String> value = Optional.of("a");

// when
List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());

// then
assertThat(collect).hasSameElementsAs(List.of("A"));
}

С другой стороны, если необязательный параметр отсутствует, вызов для него метода stream() создаст пустой поток:

@Test
public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
// given
Optional<String> value = Optional.empty();

// when
List<String> collect = value.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());

// then
assertThat(collect).isEmpty();
}

Теперь мы можем быстро фильтровать потоки дополнительных параметров.

Работа с пустым Stream не будет иметь никакого эффекта, но благодаря методу stream() теперь мы можем связать дополнительный API с Stream API. Это позволяет нам создавать более элегантный и плавный код.

5. Вывод

В этой быстрой статье мы рассмотрели дополнения Java 9 Optional API.

Мы увидели, как использовать метод or() , чтобы вернуть необязательный элемент в случае, если исходный необязательный элемент пуст. Мы использовали ifPresentOrElse() для выполнения Потребителя , если значение присутствует, и в противном случае запускали другой обратный вызов.

Наконец, мы увидели, как связать Optional с Stream API, используя метод stream() .

Реализацию всех этих примеров и фрагментов кода можно найти в проекте GitHub — это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.