Java 9 Optional улучшения
Данная статья написана командой Vertex Academy. Это одна из статей из нашего Учебника по Java 9.
1. Введение
Java 9 принесла довольно много нового в нашу жизнь, исключением не стали Optional и Stream API.
2. Stream из Optional
Да, теперь стало возможным создать Stream из Optional.
1 2 |
Optional<String> optional = Optional.of("Strange"); Stream<String> stream = optional.stream(); |
Если Optional будет пустым, то и Stream, соответственно, тоже. А теперь узнаем зачем это нужно.
Представим следующую ситуацию: нам нужно найти в базе всех персонажей по именам и вывести на экран их фамилии с помощью Java 8
Вот наша "база данных" и поиск в ней
1 2 3 4 5 6 7 8 9 |
private Map<String, String> humans = Map.of( "John", "Snow", "Aria", "Stark", "Daenerys", "Targaryen" ); private Optional<String> getSurname(String name) { return Optional.ofNullable(humans.get(name)); } |
И собственно сама логика поиска и вывода
1 2 3 4 5 6 |
List<String> names = List.of("John", "Aria", "Tyrion", "Daenerys", "Eddard"); names.stream() .map(this::getSurname) .filter(Optional::isPresent) .map(Optional::get) .forEach(System.out::println); // Snow Stark Targaryen |
Как видим, нам приходится проверять Optinal перед тем как взять его значение. Но в Java 9 это можно сделать проще, ведь мы можем сделать Stream из Optional
1 2 3 4 5 |
List<String> names = List.of("John", "Aria", "Tyrion", "Daenerys", "Eddard"); names.stream() .map(Example::getSurname) .flatMap(Optional::stream) .forEach(System.out::println); //Snow Stark Targaryen |
Результат тот же, а код выглядит более опрятным.
3. Optional.ifPresentOrElse()
Еще один полезный метод, который позволяет выполнить одно действие, если значение в Optional присутствует, и другое - если его нет.
Реализация этого метода выглядит так
1 2 3 4 5 6 7 |
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) { if (value != null) { action.accept(value); } else { emptyAction.run(); } } |
Т.е., если значение Optional присутствует, исполняется наше действие, если нет - запускается переданный Runnable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class Example { private static Map<String, String> survivors = Map.of( "John", "Snow", "Aria", "Stark", "Tyrion", "Lannister", "Daenerys", "Targaryen" ); public static void main(String[] args) { List<String> names = List.of("John", "Aria", "Tyrion", "Daenerys", "Eddard"); names.stream() .map(Example::getSurname) .forEach(s -> s.ifPresentOrElse(Example::printAlive, Example::printDead)); } private static void printAlive(String surname) { System.out.println(surname + " is alive"); } private static void printDead() { System.out.println("One more dead"); } private static Optional<String> getSurname(String name) { return Optional.ofNullable(survivors.get(name)); } } |
Вывод в консоль
1 2 3 4 5 |
Snow is alive Stark is alive Lannister is alive Targaryen is alive One more dead |
4. Optional.or()
Этот новый метод пришёл в дополнение к orElseGet(), ведь тот не до конца безопасен.
Пример
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public static void main(String[] args) { String username = "John"; String homeAddress = findHomeAddress(username) .orElseGet(() -> findWorkAddress(username)); System.out.println(homeAddress); } private static String findWorkAddress(String username) { return Math.random() > 0.2 ? username + "'s Work" : null; } private static Optional<String> findHomeAddress(String username) { return Math.random() > 0.5 ? Optional.of(username + "'s Home") : Optional.empty(); } |
Если findHomeAddress() не "найдет" адрес пользователя, вызовется метод findWorkAddress(), но если и он не "найдет" адрес, то мы получим null. Новый метод or() решает эту проблему, он принимает Supplier, который должен вернуть Optional, а не обычный объект
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public static void main(String[] args) { String username = "John"; Optional<String> address = findHomeAddress(username) .or(() -> findWorkAddress(username)); System.out.println(address); } private static Optional<String> findWorkAddress(String username) { return Math.random() > 0.5 ? Optional.of(username + "'s Home") : Optional.empty(); } private static Optional<String> findHomeAddress(String username) { return Math.random() > 0.5 ? Optional.of(username + "'s Home") : Optional.empty(); } |
На этом статья заканчивается, но не новинки Java 9. Спасибо, что были с нами 🙂
Хотите записаться к нам на курсы? Смотрите детальную информацию у нас на сайте.