Listen to the sediment spread… Pay attention to wechat public number [Java], help you give up the path of programming!

Series of articles

The title The article links
Play with Java8 Stream to make your code more efficient and compact Juejin. Cn/post / 692113…

What is Optional?

Official definition:

public final class Optional<T> extends Object

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.

Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).

This is a value-based class; use of identity-sensitivemin operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.

Optional class, a container object that may or may not contain non-null values. If the value exists, the isPresent() method returns true and get() returns the value.

This class also provides other methods that depend on the presence or absence of the value it contains, such as orElse() (which returns the default if no value exists) and ifPresent() (which executes a code block if one exists).

This is a value-based class, so some identity-sensitive operations on Optional instances (including reference equality ==, hashCode, synchronization) can produce unexpected results and should be avoided.

What is Optional?

  1. Since the Optional class can contain a value ofnull, it goes without saying that we can not explicitly carry out null value detection, that is, we can not do null judgment operation, which is a good solution to the null pointer exception problem (NullPointerException).
  2. Java8 introduces functional programming, and Optional is an essential part of it to help implement it in the paradigm. Combined with Stream, you can write clean and efficient code.

For example, print the job title of an employee. If the job name is empty, print the default value – Intern:

if (null! = staff.getPost().getName()) { System.out.println(staff.getPost().getName()); }else {
    System.out.println("Intern");
}
Copy the code

The above statement may throw an NPE. For robustness, we need to write null:

if (null! = staff) { Post post = staff.getPost();if (null! = post) { String name = post.getName();if (null! = name) { System.out.println(name); }else {
            System.out.println("Intern"); }}}Copy the code

But write a lot of empty operation, very tedious, code redundancy is difficult to maintain. If you use Optional, this is very simple:

System.out.println(
        Optional.ofNullable(staff).map(Staff::getPost).map(Post::getName).orElse("Intern"));
Copy the code


Optional source code details

public final class Optional<T> {
    
    // Contains an Optional container object with a null value
    private static finalOptional<? > EMPTY =new Optional<>();

    // Optional Specifies the value that the container contains
    private final T value;

    // Private constructor that creates an Optional container object containing null values
    private Optional(a) {
        this.value = null;
    }

    Static method that creates an Optional container object with a null value
    public static<T> Optional<T> empty(a) {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // Private constructor that creates an Optional container object containing non-null values
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // Static method that creates an Optional container object containing non-null values
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // Static method that creates an Optional container object containing nullable values
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    // Gets the value, and if the value is null, an exception is thrown
    public T get(a) {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    // Check whether the value is not null
    public boolean isPresent(a) {
        returnvalue ! =null;
    }

    // If the value is not null, the consumer function is called with the changed value
    public void ifPresent(Consumer<? super T> consumer) {
        if(value ! =null)
            consumer.accept(value);
    }

    // If the value exists and the value matches the given predicate, return an Optional description of the value, otherwise return an empty Optional.
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if(! isPresent())return this;
        else
            return predicate.test(value) ? this : empty();
    }

    // If the value exists, call the mapping function on it to get the new return value. Otherwise return empty Optional.
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if(! isPresent())return empty();
        else {
            returnOptional.ofNullable(mapper.apply(value)); }}// If the value exists, return the value of the mapping method based on the Optional inclusion, otherwise return an empty Optional
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if(! isPresent())return empty();
        else {
            returnObjects.requireNonNull(mapper.apply(value)); }}// Return this value if it exists, otherwise return other.
    public T orElse(T other) {
        returnvalue ! =null ? value : other;
    }

    // Return the value if it exists, otherwise call other and return the result of other.
    public T orElseGet(Supplier<? extends T> other) {
        returnvalue ! =null ? value : other.get();
    }

    // Returns the value if it exists, otherwise throws an exception inherited by Supplier
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if(value ! =null) {
            return value;
        } else {
            throwexceptionSupplier.get(); }}}Copy the code


The use of Optional classes

4.1 Optional object creation

// Create a null Optional object
Optional<Object> emptyOptional = Optional.empty();
// Create an Optional object with a null value
Optional<Staff> staffOptional = Optional.ofNullable(staff);
// Create a non-null Optional object
Optional<Staff> staffOptional1 = Optional.of(staff);
Copy the code

4.2 the get ()

// Returns the value contained in the Optional container object, or throws an exception if it is null
Staff staff = staffOptional.get();
Copy the code

4.3 isPresent ()

// Check whether the value exists
if (staffOptional.isPresent()) {
    Staff staff = staffOptional.get();
}
Copy the code

4.4 ifPresent (Consumer <? super T> consumer)

// Prints the value if it exists
staffOptional.ifPresent(System.out::println);
Copy the code

4.5 the filter (Predicate <? super T> predicate)

// If there is an 18-year-old employee, print her name
staffOptional.filter(staff -> staff.getAge() == 18)
                .ifPresent(staff -> System.out.println(staff.getName()));
Copy the code

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

If staff or name is null, print 'unknown'
System.out.println(staffOptional.map(Staff::getName).orElse("Unknown"));
Copy the code

4.7 orElse other (T)

// If staff is null, the newly generated staff object is assigned to the staff
staff = Optional.ofNullable(staff).orElse(new Staff());
Copy the code

4.7 orElseGet: Supplier <? extends T> other)

// // If staff is null, a new staff object will be created and assigned to staff, which differs from orElse in execution timing. OrElseGet calls other only when the value is null.
staff = Optional.ofNullable(staff).orElseGet(Staff::new);
Copy the code

4.8 orElseThrow: Supplier <? extends X> exceptionSupplier) throws X

// If staff is null, an exception is thrown
staff = Optional.ofNullable(staff).orElseThrow(() -> new NullPointerException());
Copy the code

4.9 Used with Stream

// Find an employee whose age is 18 or older
Optional<Staff> staffOptional = staffList.stream().filter(staff -> staff.getAge() >= 18).findFirst();
if (staffOptional.isPresent()) {
    Staff staff = staffOptional2.get();
}
Copy the code