Необязателен ли ваш вариант?

Java задняя часть

предисловие

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.OptionalдаJava 8Внедрение новых функций, его появление должно помочь решить проблемы, с которыми часто сталкиваются программисты.NPE(NullPointerException) проблема, но из-за читаемой строки многие редко используют его в своих проектах, а пользуются более интуитивнымif...else,я считаю,OptionalРаз уж он запущен, то он должен иметь ценность и значимость его использования.Надо научиться его понимать.Освоив его, написать элегантный и немного продвинутый код не проблема! надеятьсяOptionalбудет одна из ваших кодировокOption.

представлять

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

ЭтоJava 8 docsПервый абзац, общий профильOptionalЭто объект-контейнер, который может содержать или не содержать ненулевые значения. По сути, это класс-оболочка. Значение, хранящееся в нем, может быть любым конкретным значением.Javaтип, черезgetметод, чтобы получить значение внутри.

статический метод для создания экземпляра

Optional.empty()

  • создать пустойOptionalпример
System.out.println(Optional.empty()); // Optional.empty

Optional.of(T value)

  • Для создания текущего ненулевого значения указаноOptionalпример

  • Обратите внимание, что входящее значение не пустое, иначе будет сообщеноNPE

Пример

// 对象属性为空,并非 null
User emptyUser = new User();
System.out.println(Optional.of(emptyUser));

// User 对象为空
User nullUser = null;
System.out.println(Optional.of(nullUser)); // throw NullPointerException

// String 对象为空
String nullString = null;
System.out.println(Optional.of(nullString)); // // throw NullPointerException

Optional.ofNullable(T value)

  • Возвращает описание указанного значения, если значение не равно нулюOptional, иначе возвратOptional.empty(), не выдает исключение

Пример

// 对象属性为空,并非 null
User emptyUser = new User();
System.out.println(Optional.ofNullable(emptyUser)); // Optional[User{id=null, name='null', sex='null', age=null, salary=null}]

// User 对象为空
User nullUser = null;
System.out.println(Optional.ofNullable(nullUser)); // Optional.empty

// String 对象为空
String nullString = null;
System.out.println(Optional.ofNullable(nullString)); // Optional.empty

резюме

  • использоватьOptionalПрежде чем вам нужно будет использовать три вышеуказанных статических метода для создания экземпляра

  • Создайте пустой экземпляр, используяOptional.empty()

  • Если вы хотите создать ненулевой экземпляр, рекомендуется использоватьOptional.ofNullable(), можно указать, что входящие параметры неnull,можно использоватьOptional.of()способ создать.

Часто используемые методы экземпляра

isPresent()

  • Используется, чтобы определить, существует ли обернутое значение, если значение существует, вернуть true , в противном случае вернуть false

Пример

Optional<User> opt1 = Optional.of(emptyUser); // Optional[User{id=null, name='null', sex='null', age=null, salary=null}]

Optional<User> opt2 = Optional.ofNullable(nullUser); // Optional.empty

System.out.println(opt1.isPresent() ? "包装值存在" : "包装值不存在"); // 包装值存在
System.out.println(opt2.isPresent() ? "包装值存在" : "包装值不存在"); // 包装值不存在

ifPresent(Consumer<? super T> consumer)

  • еслиOptionalЕсли экземпляр имеет значение, для него вызывается объект функцииconsumer, иначе не обрабатывать

Как понять функционал интерфейса Consumer?

// 消费者方法
private static void consumerMethod(User user, Consumer<User> cu) {
    cu.accept(user);
}

// main 主方法中调用
User user01 = new User(42, "石天苟", "女", 16, 4520);
consumerMethod(user01, user1 -> System.out.println(user1.getName() + user1.getSex())); // 石天苟女

Consumerэто потребительский интерфейс, который получает сегменты кода интерфейса илиLambdaвыражение, общий метод заключается в использованииaccept()этот абстрактный метод использует входящее значение и не имеет возвращаемого значения.Функция (или сегмент кода) потребляется, а логический код инкапсулируется.

Пример

// opt1、opt2 定义见上
opt1.ifPresent(System.out::println); // User{id=null, name='null', sex='null', age=null, salary=null}
opt2.ifPresent(System.out::println); // 无任何输出

get()

  • Если обернутое значение существует, изOptionalДостаньте из пакета и верните, иначе выбросьтеNoSuchElementExceptionаномальный

Пример

User user = opt1.get();
opt2.get(); // throw NoSuchElementException: No value present
System.out.println(user); // User{id=null, name='null', sex='null', age=null, salary=null}

orElse(T other)

  • Возвращает значение, если оно существует, иначе возвращаетother

Пример

User user02 = new User(20, "李四", "女", 15, 2350);
// opt2 为 null,所以返回 other => user02
User orElse = opt2.orElse(user02); 
System.out.println(orElse); // User{id=20, name='李四', sex='女', age=15, salary=2350}

orElseGet(Supplier<? extends T> other)

  • Возвращает значение, если оно существует, иначе вызываетotherи возвращает результат этого вызова. прием параметраSupplierреализация интерфейса,OptionalОн содержит значение возвращаемого значения, в противном случае возвращаемое значение изSupplierПолучать

Как понять функционал интерфейса Поставщика?

// 提供者/供应商方法
private static User supplierMethod(Supplier<User> su) {
    return su.get();
}

// main 主方法中调用
User user03 = new User(42, "王麻子", "男", 29, 4000);
System.out.println(supplierMethod(() -> user03)); // User{id=42, name='王麻子', sex='男', age=29, salary=4000}

Supplierэто интерфейс провайдера, который получает сегменты кода интерфейса илиLambdaвыражение, общий метод заключается в использованииget()метод, абстрактный метод получит результат, какие бы данные ни были переданы, что можно понять как «посадить бобы и получить бобы, посеять дыни и получить дыни».Предоставляет функции (или сегменты кода) и инкапсулирует логический код.

Пример

orElseThrow(Supplier<? extends X> exceptionSupplier)

  • Возвращает содержащееся значение, если оно существует, в противном случае выбрасываетexceptionSupplierисключение создано

Пример

try {
    // opt2 为 null,所以抛出提供的异常
    User elseThrow = opt2.orElseThrow(NullPointerException::new);
    System.out.println(elseThrow);
}catch (Exception e) {
    System.out.println(e); // java.lang.NullPointerException
}

filter(Predicate<? super T> predicate)

  • Если обернутое значение существует и соответствуетpredicateусловие, возвращает описание значенияOptional, иначе возвратOptional.empty

Пример

Optional<User> opt = Optional.ofNullable(user02)
        .filter(u2 -> u2.getSalary() > 6000);
        
// 没有满足 predicate 的条件
System.out.println(opt); // Optional.empty

map(Function<? super T,? extends U> mapper)

Анализ исходного кода

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}
  • Если значение существует, примените к нему предоставленную функцию сопоставления и верните значение с помощьюOptional.ofNullableупакованныйOptional

Пример

Integer newNameLens =
        Optional.of(user03) // Optional<User>
                .map(u3 -> u3.getName() + '-' + u3.getSex()) // 到这返回的是 Optional<String>
                .map(newName -> newName.trim()) // 到这返回的还是 Optional<String>
                .map(newName -> newName.length()) // 到这返回的是 Optional<Integer>
                .get(); // 取出 Optional 中包装值
                
System.out.println("通过 Map 映射处理后,得到新名字长度:" + newNameLens); // 通过 Map 映射处理后,得到新名字长度:5

flatMap(Function<? super T,Optional> mapper)

Анализ исходного кода

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}
  • Если значение существует, примените к нему предоставленную функцию сопоставления и верните значение с помощьюObjects.requireNonNullупакованныйOptional, если результат функции сопоставления пуста, она будет сообщатьNPE

Пример

user02.setName("诸葛大力");
String firstName = Optional.ofNullable(user02) // // 到这返回的是 Optional<User>
        .flatMap(u2 -> Optional.of(u2.getName())) // 到这返回的是 Optional<String>
        .flatMap(name -> {
            String familyName;
            if (name.length() <=3) {
                familyName = name.substring(0, 1);
            } else {
                familyName = name.substring(0, 2);
            }
            return Optional.of(familyName);
        }) // 到这返回的还是 Optional<String>

System.out.println("经过 flatMap 映射处理之后,用户名姓氏:" + firstName); // 诸葛

резюме

  • Когда существует обернутое значение, вы можете получить описание значенияOptional

  • Будьте осторожны, чтобы избежать, когда обернутое значение может не существоватьNPEисключение, создатьOptionalИспользуйте static при переносе классовofNullable(), добавить в конец цепочкиorElse...()Логика, когда значение равно нуле или бросает соответствующую информацию об исключении. Кроме того, вы также можете использоватьisPresent()пустой,ifPresent()Метод использует возможное значение пакета. Не имеет значения, пусто ли значение в данный момент, и оно не будет обработано или сообщено.NPE

  • Optionalметод экземпляраmap()а такжеflatMap()Разница в том, что результат функции карты является конкретным и может быть нулевым, в то время как последнийOptionalи не может быть пустым, иначеNPEдоговариваться

Использование сценария

Нулевое преобразование

String avatarUrl = null;
User user = new User("HUALEI", url);

String userAvatarUrl = Optional.ofNullable(user)
                       .map(u -> u.getUserAvatar()).orElse("https://p3-passport.byteacctimg.com/img/user-avatar/7c53d8cf8b3f3de699f1db654b88063d~300x300.image");

user.setUserAcatar(avatarUrl);

Если пользователь не устанавливает аватар, используется аватар по умолчанию.

Integer salary = Optional.ofNullable(emptyUser)
        .map(u -> u.getSalary())
        .orElse(0);

emptyUser.setSalary(salary);

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

фильтрация значений

Проверьте формат номера мобильного телефона, обычное написание:

String phone = "12345678910";
String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\d{8}$";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(phone);
boolean isMatch = m.matches();
if(isMatch){
    System.out.println("手机号格式正确");
} else {
    System.out.println("手机号码格式错误");
}

использоватьOptional.filter()фильтрация методов

boolean isValid = Optional.ofNullable(user)
                                .filter(u -> {
                                    Pattern pattern = Pattern.compile(regex);
                                    return pattern.matcher(u.getPhone()).matches();
                                })
                                .isPresent();

assertTrue(isValid);

смешанная операция

список сотрудников

User user01 = new User(42, "石天苟", "女", 16, 4520);
User user02 = new User(20, "李四", "女", 15, 2350);
User user03 = new User(42, "王麻子", "男", 29, 4000);
List<User> users = new ArrayList<User>() {{
    add(user01);
    add(user02);
    add(user03);
}};

Чтобы найти общую заработную плату работника, мы могли бы написать это раньше:

// 计算工资累加器
int sumSalary = 0;

// 在增强 for 循环中累加每个非空用户的工资
if (users != null) {
    for (User u : users) {
        if(u != null) {
            sumSalary += u.getSalary();
        }
    }
}

System.out.println("员工总工资:" + sumSalary); // 员工总工资:10870

прочитай этоФункциональные операции с потоками — самородки (juejin.cn)Вы можете написать это:

Integer sumSalary = 0;

if (users != null) {
    sumSalary = users.stream()
            .filter(Objects::nonNull)
            .map(User::getSalary)
            .reduce(0, (sum, currentValue) -> sum + currentValue);
}

System.out.println("员工总工资:" + sumSalary); // 员工总工资:10870

Но вы бы так написали?

29B28A11.jpg

Integer sumSalary = Optional.ofNullable(users).map(us -> {
    Integer sum = 0;
    for (User user : us) {
        sum += Optional.ofNullable(user).map(User::getSalary).orElse(0);
    }
    return sum;
}).orElse(0);

System.out.println("员工总工资:" + sumSalary); // 员工总工资:10870

конец

Нелегко писать статью. Вы можете ставить лайки и комментировать. Ваше внимание и лайки — это неустанная движущая сила для меня, чтобы продолжать работать. Спасибо, что вы здесь! Мир и любовь.