Author: Tangyuan

Personal blog: Javalover.cc

preface

Officials hello, I am tangyuan, today to bring you is “Java8 Optional operation”, I hope to help, thank you

The article is purely original, personal summary is inevitable mistakes, if so, please reply in the comment section or background private letter, thanks

Recently I saw a few fans (secretly happy), more words I do not say, welcome to join our big family of glory and wealth

Introduction to the

Purpose: Optional is used to solve the null pointer problem, also known as NPE.

Optional looks like a container (it is a container), except this container is special because it can hold only one object, which is, if you’re unlucky, null

The Optional operation is similar to the previous Stream operation, such as filter – extract map, etc

Let’s look at some of the basic uses of Optional with a simple example

Let’s take a look at the table of contents

directory

  1. What is Optional

  2. Without it versus with it

  3. Core operations

  4. application

The body of the

1. What is Optional

Optional is a container that can hold only one object (can be null)

Optional came along

  • One is to solve the PROBLEM of NPE (Ali development manual also mentioned this point, click to download directly, the official link)
  • Another is to make the code more legible, since the name Optional was inspired by the English languageoptional(Optional), which means the object can be empty or not empty

2. Without it vs. with it

Let’s compare the old code with the new code (Java8 as the dividing line)

Case 1: We have class C and we want to extract the C.name attribute

public class OptionalDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
      // Pass in null as an example
      getName(null);
    }
    / / remove from ame
    public static void getName(C c){
        // Old code before Java8String name = (c! =null ? c.getName() : DEFAULT_NAME);
        System.out.println("old: "+name);
        // After the new code Java8 (the following three operations will be introduced later, here is a brief introduction)
        String nameNew = Optional
            				// The factory method creates an Optional
      
        object, or an empty Optional
       
         object if C is null
       
      
                            .ofNullable(c)
            				If c==null, NPE (Optional
      
       ) is not raised. If c==null, Optional
       
         is returned
       
      
                            .map(c1->c1.getName())
            				// Gets the optional attribute value, or if null, returns the given argument DEFAULT_NAME
                            .orElse(DEFAULT_NAME);

        System.out.println("new: "+nameNew); }}class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
  / / omit getter/setter
}
Copy the code

At first glance, it seems that the old code before Java8 is more suitable, requiring only a ternary operator

If you look at the Optional operation, it’s not that neat

Well, if it’s just one judgment, then ordinary if judgments are easier to make;

But what about nesting two layers, such as b.etc ().getName()?

Now let’s see, what happens to two levels of nesting

Example 2: Now there is a class B (dependent on class C), we want to extract the property name of C from object B, i.e. B.etc ().getName()

public static void getName2(B b){
        / / the old codeString name = (b! =null? ( b.getC()! =null ? b.getC().getName() : DEFAULT_NAME) : DEFAULT_NAME);
        / / the new code
        String nameNew = Optional
                .ofNullable(b)
                .map(b1->b1.getC())
                .map(c1->c1.getName())
                .orElse(DEFAULT_NAME);
        System.out.println(nameNew);
    }

class B{
    private C c;

    public B(C c) {
        this.c = c;
    }
  / / omit getter/setter
}
Copy the code

This time, at first glance, and consistently, It looks like Optional is winning

Example 3: There is an extra class A (dependent on class B) and we want to extract a.geb ().getc ().getName()

Wait, wait, wait, ellipsisCopy the code

The Optional operator is better than the trinary operator (if/else, it’s more nested).

3. Core operations

Since Optional primarily operates on data (similar to database operations), we’ll look at it from a data perspective

Here we can divide into three operations: saving data, processing data, and retrieving data

Save data:

  • (No default value)public static <T> Optional<T> of(T value) : fills T value into the Optional property; If value==null, the NPE is thrown
  • (Default null)public static <T> Optional<T> ofNullable(T value) : fills T value into the Optional property; If the reference is NULL, null is populated
  • (Construct an empty Optional)public static<T> Optional<T> empty(): Simply create a null Optional, i.e. populate the Optional property with null.

Processing data:

  • (extraction)public<U> Optional<U> map(Function<? super T, ? extends U> mapper) : Extracts an attribute value U from the Optional attribute T, populates U into the new Optional and returns it
  • (filtering)public Optional<T> filter(Predicate<? super T> predicate) : Filters the value of an attribute in the Optional attribute T, populates T into the new Optional and returns the value
  • (Flat extraction)public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper): Extracts an attribute of the Optional property TOptional<U>, return directly

Get data:

  • public T orElse(T other): Retrieves data. If the data is null, T other is returned
  • public T orElseGet(Supplier<? extends T> other): retrieves data. If the data is null, a new data T is returned via the functional interface OTHER
  • public T get() : Fetch data. If the data is null, report NPE.

Less commonly used of these operations are get() and empty()

I won’t mention anything else, but I’ll focus on map() and flatMap().

As shown below:

Map () essentially extracts the attribute name of the attribute C in the Optional and then wraps it into the new Optional

Type Optional

, print Optional

(that is, Optional

)


String nameNew = Optional
                    .ofNullable(c)
                    .map(c1->c1.getName())
                    .orElse("xxx");
Copy the code

FlatMap () mainly extracts property B in OptionalOptional<C>Property, and then wrapped into the new Optional

So we say Optional, we say Optional

public class FlatMapDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
        getName(null);
    }

    / / remove B.C.N ame
    public static void getName(B b){
        C c = Optional
                .ofNullable(b)
            	// Here flattens out the C in Optional
      
            	// If map is used, it returns Optional
      
       >
      
                .flatMap(b->b.getC())
                .orElse(new C("xxx")); System.out.println(c.getName()); }}class B{
    private Optional<C> c;

    public Optional<C> getC(a) {
        return c;
    }

    public void setC(C c) {
        this.c = Optional.ofNullable(c); }}class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
    / / omit getter/setter
}
Copy the code

4. The application

From a specification point of view, for code clarity, if you look at the Optional

variable, you know that T may be null;

In terms of coding, it is mainly used in non-null judgment; But in the real world, there are two

  1. Parameters that are not wrapped with Optional: for example, in the example above, the passed parameter is a normal object, so we need to wrap the passed parameter with Optional container and proceed
/ / remove from ame
public static void getName(C c){
    // Optional
      
    String nameNew = Optional
        .ofNullable(c)
        .map(c1->c1.getName())
        .orElse(DEFAULT_NAME);

    System.out.println("new: "+nameNew);
}
Copy the code
  1. For example, we can use Optional to wrap the result of a database query and return it with Optional. In this way, we can only use orElse() to retrieve the result and set the default value
// Return Optional
      
       . OrElse (defaultCar) can be used to obtain the return value. If the return value is null, a default value of defaultCar can be set
      
Optional<Car> selectOne(SelectStatementProvider selectStatement);
Copy the code

conclusion

  1. What is Optional: a container that holds an object that can be null

  2. Without it vs. with it: Look at the scene

    • If it’s just a single if/else judgment, it’s better not to have it;

    • If there is a lot of nesting, or if the data is of Optional type, then it must be Optional

  3. Core operations: I will not write here those that are not commonly used

    • Save data: factory approachof()andofNullable()
    • Processing data: map(), filter(), flatMap()
    • Get data: orElse()
  4. Application: mainly used in non-null judgment, the actual scene, we can use in the database query statement

Afterword.

And finally, thank you for watching. Thank you

Original is not easy, look forward to the three even yo