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?
- Call the isPresent() method
- Call the get() method
- The Optional type is used as a class/instance attribute
- The Optional type is used as the method parameter
Explain:
- Using isPresent() and using obj! =null without any difference
- 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 |