This is the 30th day of my participation in the More Text Challenge. For more details, see more text Challenge


I think it is very difficult to write 30 articles in a row. Fortunately, I saved a large part of it before. Otherwise, according to my liver, it must not move.

Think about it in another way, just look at the continuous text is not difficult, most of the first thought should be the force buckle brush questions, this question bank, solution, language are many, enough to complete the task,

Therefore, we can also see that many of the nuggets that persist to 30 days are algorithm problems, which is also the most criticized place of this activity, too much “hydrology”,

But as long as the article is the product of their own brain thinking, each line of code is personally typed, and the accuracy of the article can be guaranteed,

Even if it’s not sophisticated, it’s meaningful to the author, to the reader,

Day watch activities are also available at other sites such as Short Book, which is more about cultivating a habit of continuous learning input and output,

To produce consistently high-quality output, you need to suppress the desire for comfort, you need to chew through obscure books, and you need to debug painful source code

If you don’t learn something new, I think maybe 30 days is enough to drain a person’s reserves

You and I are all mortals. Learn a little more today, and ask for less tomorrow

You have to be the best, and you have to impress everyone

Elegant empty

Java8 has added a number of useful apis

Is it just about NPE?

For those of you who have seen Optional’s description briefly, you might think that it solves the NPE(NullPointExcepiton) problem, so the code looks like this:

List<Order> getOrders(User u) {
    Optional<User> user = Optional.ofNullable(u);
    if (user.isPresent()) {
        return user.get().getOrders();
    }
    return Collections.emptyList();
}
Copy the code

Is that the right way to write it? Yeah, that’s fine, but is that different from the way we wrote it?

List<Order> getOrders(User u) {
    if(u ! =null) {
        return user.getOrders();
    }
    return Collections.emptyList();
}
Copy the code

It doesn’t really make a difference, because the mind is still in the same place, and the instinct is that it’s just a wrapper for the User instance.

If you want to use Optional, you need to write more, so this API is meaningless, right?

That is we did not understand the intention of the designer, not elegant use!

How elegant?

When switching to Java 8 Optional, you should master the new and correct attitude to use null.

Need to know a little bit of Java function programming knowledge, appendix has the Optional use of the function interface description

What are the wrong postures before using the right ones?

  1. Call the isPresent() method
  2. Call the get() method
  3. The Optional type is used as a class/instance attribute
  4. The Optional type is used as the method parameter

Explain:

  1. Using isPresent() and using obj! =null without any difference
  2. A direct call to get() will not throw an NPE, but will throw a NoSuchElementException if there is no value. The source code for this method is as follows:
  /**
     * If a value is present in this {@code Optional}, returns the value,
     * otherwise throws {@code NoSuchElementException}.
     *
     * @return the non-null value held by this {@code Optional}
     * @throws NoSuchElementException if there is no value present
     *
     * @see Optional#isPresent()
     */
public T get(a) {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}
Copy the code

3 and 4 use Optional types as attributes or method parameters, which is not desirable.

IsPresent (), get(), isPresent(), get()

methods describe
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) If the value exists, the provided mapping function is called to the value
public T orElse(T other) Return a value if there is one, otherwise return a default value
public T orElseGet(Supplier<? extends T> other) Returns a value if any, otherwise returns a value generated by the specified Supplier interface
public void ifPresent(Consumer<? super T> consumer) If the value exists, do the method call that uses that value, otherwise do nothing
public Optional<T> filter(Predicate<? super T> predicate) If the value exists and satisfies the supplied predicate, the Optional object containing the value is returned
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) If the value exists, the provided mapping function call is made to the value
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X Returns a value if any, or throws an exception generated by the specified Supplier interface

Before introducing the above seven methods, let’s introduce the three construction methods of Optional:

  • Optional.of(obj)
  • Optional.ofNullable(obj)
  • Optional.empty()

Optional. Of (obj): This requires that obj not be null, otherwise NullPointerException will be thrown before the role is even started.

Option.ofnullable (obj): It constructs an Optional instance in an intelligent, tolerant way. If you pass null, you get option.empty (). If not null, you call option.of (obj).

Optional. Empty (): the empty Optional

How about we just use Optional. OfNullable (obj) to construct the Optional instance once and for all? Not necessarily, otherwise Optional. Of (obj) why so exposed, private can?

When we are very, very clear that the obj argument to be passed to Optional. Of (obj) cannot be null, for example if it is a new object (Optional. Of (new User(…)) )), or a non-null constant; 2. When we want to assert that obj is not null, that is, we want to immediately report a NullPointException in case obj is null, instead of hiding the null pointer exception, We should use Optional. Of (obj) to construct an Optional instance without any unexpected null value.

If (user.ispresent ()) {if(user.ispresent ()) {if(user.ispresent ()) {… } else {… } several application mode.

If it exists, the value is returned. If it does not, the default value is provided
return user.orElse(null);  // instead of return user.ispresent ()? user.get() : null;
return user.orElse(UNKNOWN_USER);
Copy the code
If it exists, it returns; if it does not, it is generated by the function
return user.orElseGet(() -> fetchAUserFromDatabase()); 
// instead of return user.ispresent ()? user: fetchAUserFromDatabase();
Copy the code
To do something about it
user.ifPresent(System.out::println);
// Not like below
if (user.isPresent()) {  
	System.out.println(user.get());
}
Copy the code
Use of the map function

If user.ispresent () is true, it returns an empty set of orders, and if false, it returns an empty set of orders. If user.ispresent () is true, it returns an empty set.

return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
Copy the code

Before Java 8:

if (user.isPresent()) {
    return user.get().getOrders();
} else {
    return Collections.emptyList();
}
Copy the code

And maps can be cascaded, at a deeper level:

return user.map(u -> u.getUsername()).map(name -> name.toUpperCase()).orElse(null);
Copy the code

In the old days we would have written this:

User user = new User();
if(user ! =null) {
    String name = user.getUsername();
    if(name ! =null) {
        return name.toUpperCase();
    } else {
        return null; }}else {
    return null;
}
Copy the code

Using isPresent() to handle NullPointerException is not elegant. OrElse, orElseGet, and especially map methods are elegant.

The use of the filter
// The filter method checks whether the given Option value meets certain conditions. // If yes, return the same Option instance, otherwise the empty Optional is returned. Optional
      
        longName = name.filter((value) -> value.length() > 6); System.out.println(longName.orElse("The name is less than 6 characters")); // Sanaulla// Another example is when the Optional value does not satisfy the filter criteria. Optional
       
         anotherName = Optional.of("Sana"); Optional
        
          shortName = anotherName.filter((value) -> value.length() > 6); System.out.println(shortname.orelse ("The name is less than 6 characters")); // Output: The name is less than 6 characters.
        
Copy the code
The use of orElseThrow
return user.orElseThrow(()->new NullPointException("No user"));
Copy the code

or

return user.orElseThrow(NullPointException::new);
Copy the code

A one-sentence summary: When using Optional, try not to call option.get () directly. Option.ispresent () should be treated as a private method and should rely on other methods like option.orelse (), Option.orelseget (), option.map (), and so on.

Optional uses the function interface
The function interface instructions
Predicates Predicate is a Boolean function that takes only one input parameter
Function The Function interface takes one parameter and returns a single result
Supplier The Supplier interface produces a result of a given type. Unlike Function, Supplier has no input parameters.
Consumer The Consumer represents the action that needs to be performed on an input parameter