Java 8 Optional Conscience Guide, recommended collection

It's never too late to learn, especially about the great things in Java 8, and Optional is one of them, providing a class-level solution that represents alternative values rather than empty references.As a Java programmer, I'm really sick of NullPointerException (NPE), even though I know it like an old friend and have to know it too - the program is using an object and finds its value null, so the Java Virtual Machine angrily throws it out as a scapegoat.

Of course, our programmers are responsible and don't just sit back and have a lot of null checks.Sometimes this kind of inspection is completely unnecessary, but we are used to the routine.Finally, when Java 8 couldn't look any further, Optional was introduced so that the code we wrote wasn't too rigid.

01. What's wrong without Optional

Let's simulate an actual application scenario.The first day Xiao Wang went to work, the leader Lao Ma arranged a task for him to pull a member's name from the database according to the member ID, and then print the name to the console.Although he was new to the project, it was a difficult task for Wang, so he spent 10 minutes writing the code:

public class WithoutOptionalDemo {
    class Member {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        Member mem = getMemberByIdFromDB();
        if (mem != null) {
            System.out.println(mem.getName());
        }
    }

    public static Member getMemberByIdFromDB() {
        //Current ID member does not exist
        return null;
    }
}

Since the current ID member does not exist, the getMemberByIdFromDB() method returns null as a result of not getting the member, which means that when you print the member's name, you must first empty the mem, otherwise you will throw an NPE exception, don't believe it?Let Xiao Wang try to remove if (mem!= null), and the console will print the error stack to show you the color.

Exception in thread "mainjava.lang.NullPointerException
    at com.cmower.dzone.optional.WithoutOptionalDemo.main(WithoutOptionalDemo.java:24)

02. How Optional solves this problem

After Xiao Wang submitted the code, he went to the old horse in high spirits to ask for a new task.With an attitude of modest learning, Xiao Wang asked Lao Ma to look at his code, so he told him that he should try Optional to avoid unnecessary null value checks.Now let's see how Xiao Wang solved these problems with Optional.

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<Member> optional = getMemberByIdFromDB();
        optional.ifPresent(mem -> {
            System.out.println("Members'names are:" + mem.getName());
        });
    }

    public static Optional<Member> getMemberByIdFromDB() {
        boolean hasName = true;
        if (hasName) {
            return Optional.of(new Member("Silent King Two"));
        }
        return Optional.empty();
    }
}
class Member {
    private String name;

    public String getName() {
        return name;
    }

    // getter / setter
}

The getMemberByIdFromDB() method returns Optional <Member> as a result, indicating that Members may or may not exist, at which point Lambda expressions can be used in Optional's ifPresent() method to print the results directly.

Optional solves the NPE problem because it explicitly tells us that there is no need to void it.It's like a sign at an intersection, telling you exactly where to go.

03. Create Optional Object

1) An empty Optional object can be created using the static method empty()

Optional<String> empty = Optional.empty();
System.out.println(empty); //Output: Optional.empty

2) You can use the static method of() to create a non-empty Optional object

Optional<String> opt = Optional.of("Silent King Two");
System.out.println(opt); //Output: Optional [Silent King Two]

Of course, the parameter passed to the of() method must be non-empty, meaning it cannot be null, or a NullPointerException will still be thrown.

String name = null;
Optional<String> optnull = Optional.of(name);

3) You can use the static method ofNullable() to create an Optional object that can be empty or not.

String name = null;
Optional<String> optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull); //Output: Optional.empty

There is a ternary expression inside the ofNullable() method that returns the private constant EMPTY if the parameter is null; otherwise, a new Optional object is created using the new keyword -- NPE exceptions are no longer thrown.

04. Determine whether the value exists

The isPresent() method can be used to determine whether an Optional object exists. If it does, it returns true, otherwise it returns false - instead of obj!= null.

Optional<String> opt = Optional.of("Silent King Two");
System.out.println(opt.isPresent()); //Output:true

Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); //Output: false

After Java 11, you can also use the isEmpty() method to determine the opposite result from isPresent().

Optional<String> opt = Optional.of("Silent King Two");
System.out.println(opt.isPresent()); //Output: false

Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); //Output:true

05, Non-empty expression

The Optional class has a very modern method, ifPresent(), that allows us to execute some code using functional programming, so I call it a non-empty expression.If there is no such method, we usually need to null the Optional object by isPresent() before executing the corresponding code:

Optional<String> optOrNull = Optional.ofNullable(null);
if (optOrNull.isPresent()) {
    System.out.println(optOrNull.get().length());
}

With ifPresent(), the situation is completely different, and Lambda expressions can be passed directly to this method, making the code more concise and intuitive.

Optional<String> opt = Optional.of("Silent King Two");
opt.ifPresent(str -> System.out.println(str.length()));

After Java 9, two results can also be executed through the method ifPresentOrElse(action, emptyAction), which executes action in non-empty time and emptyAction in empty time.

Optional<String> opt = Optional.of("Silent King Two");
opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("Is empty"));

06, Set (Get) Default Value

Sometimes, when we create (get) an Optional object, we need a default value, and the orElse() and orElseGet() methods come in handy.

The orElse() method returns the value wrapped in the Optional object if it is not null; otherwise, it returns the default value.The parameter type and value type of this method are identical.

String nullName = null;
String name = Optional.ofNullable(nullName).orElse("Silent King Two");
System.out.println(name); //Output: Silence King Two

The orElseGet() method is similar to the orElse() method, but the parameter types are different.If the value in the Optional object is null, the function in the parameter is executed.

String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(()->"Silent King Two");
System.out.println(name); //Output: Silence King Two

These two methods are very similar in terms of output and code form, which raises our suspicion. Is it necessary for the designer of the Java class library to do this?

Suppose there is such a traditional way to get default values.

public static String getDefaultValue() {
    System.out.println("getDefaultValue");
    return "Silent King Two";
}

The getDefaultValue() method is then called to return the default value through the orElse() method and the orElseGet() method, respectively.

public static void main(String[] args) {
    String name = null;
    System.out.println("orElse");
    String name2 = Optional.ofNullable(name).orElse(getDefaultValue());

    System.out.println("orElseGet");
    String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}

Note: Class name: Method name is a syntax introduced in Java 8, and method name is not followed by (), indicating that the method may not necessarily be called.

The output is as follows:

orElse
getDefaultValue

orElseGet
getDefaultValue

The output results are similar, but not very different, when the value of the Optional object is null.What if the value of the Optional object is not null?

public static void main(String[] args) {
    String name = "Silent King Three";
    System.out.println("orElse");
    String name2 = Optional.ofNullable(name).orElse(getDefaultValue());

    System.out.println("orElseGet");
    String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}

The output is as follows:

orElse
getDefaultValue
orElseGet

Well, orElseGet() did not call getDefaultValue().Do you understand which method performs better?

07, Get Value

Semantically, the get() method is the most authentic way to get the value of an Optional object, but unfortunately, it is flawed because it throws a NoSuchElementException exception if the value of the Optional object is null.This is completely contrary to our original intention of using the Optional class.

public class GetOptionalDemo {
    public static void main(String[] args) {
        String name = null;
        Optional<String> optOrNull = Optional.ofNullable(name);
        System.out.println(optOrNull.get());
    }
}

This program throws an exception when it runs:

Exception in thread "main" java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.get(Optional.java:141)
    at com.cmower.dzone.optional.GetOptionalDemo.main(GetOptionalDemo.java:9)

Although the exception thrown is NoSuchElementException, not NPE, it appears to us that it is clearly a "50-step laugh".It is recommended that the orElseGet() method get the value of the Optional object.

08. Filter Value

Xiao Wang upgraded the previous code through the Optional class, and when finished, he ran happily to find the old horse's important task.The old horse thought this young man was good, flexible and active, and worth cultivating. He gave him a new task: checking the length of the password when the user registered.

When Xiao Wang got his task, he was happy to have a flower because he was just going to learn the filter() method of the Optional class, which came in handy.

public class FilterOptionalDemo {
    public static void main(String[] args) {
        String password = "12345";
        Optional<String> opt = Optional.ofNullable(password);
        System.out.println(opt.filter(pwd -> pwd.length() > 6).isPresent());
    }
}

The parameter type of the filter() method is Predicate (a new functional interface in Java 8), which means that a Lambda expression can be passed to the method as a condition. If the result of the expression is false, an EMPTY Optional object is returned, otherwise a filtered Optional object is returned.

In the example above, the program output is false because the password length is 5.Assuming the length of the password is between 6 and 10 bits, another condition can be appended.See the code after Xiao Wang added difficulty.

Predicate<String> len6 = pwd -> pwd.length() > 6;
Predicate<String> len10 = pwd -> pwd.length() < 10;

password = "1234567";
opt = Optional.ofNullable(password);
boolean result = opt.filter(len6.and(len10)).isPresent();
System.out.println(result);

The output of this program is true because the password has changed to 7 bits, between 6 and 10 bits.Imagine how long the code would be if Wang used if-else to accomplish this task.

09. Conversion Value

After checking the length of the password, Xiao Wang still felt not happy enough and felt that he had to check the strength of the password, for example, the password could not be "password", which is too weak.Then he began to study the map() method, which converts the original Optional object into a new Optional object according to certain rules, and the original Optional object will not be changed.

Let's start with a simple example written by Xiao Wang:

public class OptionalMapDemo {
    public static void main(String[] args) {
        String name = "Silent King Two";
        Optional<String> nameOptional = Optional.of(name);
        Optional<Integer> intOpt = nameOptional
                .map(String::length);

        System.out.println( intOpt.orElse(0));
    }
}

In the example above, the parameter String::length of the map() method means that an Optional of the original string type will be regenerated to a new Optional object of type Integer according to the length of the string.

After clarifying the basic usage of the map() method, Wang decided to combine the map() method with the filter() method, which converts passwords to lowercase, and the latter which determines length and whether it is a "password".

public class OptionalMapFilterDemo {
    public static void main(String[] args) {
        String password = "password";
        Optional<String>  opt = Optional.ofNullable(password);

        Predicate<String> len6 = pwd -> pwd.length() > 6;
        Predicate<String> len10 = pwd -> pwd.length() < 10;
        Predicate<String> eq = pwd -> pwd.equals("password");

        boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();
        System.out.println(result);
    }
}

Okay, my dear reader friend, that's all there is in this article - the best Optional guide in history, the best programmers you can see here, and the two brothers have to hold out their thumbs to compliment you.

If you find this article helpful to you, please WeChat to search for "Silence King II" for the first time to read, reply to "666" [1024]. There are also 500G HD instructional videos (categorized) that I have prepared for you, and a face sorted by Dachang Technical Bullman. The source code is included in CodeCloud. Portal~

Tags: Java Lambda Database Programming

Posted on Mon, 09 Mar 2020 21:43:29 -0400 by ketola