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, поэтому его должно быть легко импортировать и запускать как есть.