In the present work, I have to use a lot of Java in the Stream and Lambda expressions, before also wrote two articles summarize the corresponding knowledge.
- 024: Java stream realize Shell: cat 1.log | grep a | sort | uniq -c | sort -rn
- Functional programming design patterns let you forget
Optional but for this feature has not been well used up, so recently started reading "Java 8 real" book, this is where the Chapter 10 for a study summary.
background
In Java, if you attempt to make null function call, it will trigger NullPointerException (NPE), NPE is the most typical abnormal Java program development for Java developers, whether you are inexperienced newcomers and also worked for many years old driver, NPE often let them roll. To avoid NPE, they will add a lot if the judge sentences, making the code readability becomes poor.
From a software design point of view, null itself is meaningless semantics, this is the wrong kind of modeling missing variable values.
From the perspective of the Java type system perspective, null can be assigned to any type of variable, and continues to be passed, and finally know who do not know where it was introduced.
Optional introduction of
Java designers get inspiration from Haskell and Scala, the introduction of a new class in Java 8 in java.util.Optional<T>
. If an interface return Optional, can represent a person may or may not have a car the car, the Car than a simple return to be more clear, people do not need to read the code of business knowledge to prepare in advance.
Optional objective lies in this: by type of system allows your domain model hidden knowledge explicitly reflected in your code.
Optional use of
method | description |
---|---|
empty | Optional return an empty instance |
filter | If the value exists and filtered to provide the condition is satisfied, the return value is an object containing Optional; otherwise returns an empty Optional objects |
map | If the value exists, mapping function to perform on the value of the calls provided |
flatMap | If the value exists, it is executed to provide the mapping function value of the call, the return value of a type Optional, otherwise it returns an empty Optional objects |
ifPresent | If the value exists, the implementation method of using the value of the call, otherwise do nothing |
of | After the specified value Optional package returned, if the value is null, throw an NPE |
ofNullable | After the specified value Optional package returned, if the value is null, an object is returned empty Optional |
orelse | If there is value is returned, otherwise a default value |
orElseGet | If value is returned, otherwise a Supplier generated by the designated interface value (default value if the cost of generating relatively high, then suitable methods orElseGet) |
orElseThrow | If the value is returned, otherwise a return by the specified exceptions thrown Supplier Interface |
get | If the value exists, the value is returned, otherwise an exception is thrown a NoSuchElementException |
isPresent | If the value is returned there is true, false otherwise |
This table lists the basic API Optional above, I Here are a few tips to use:
- You can use ofNullable may be a null object encapsulation for Optional object, and then get the time value of using orElse method to provide default values; you can create an object using empty empty Optional method; of methods generally do not, but if you know a impossible to null value, this value can be used Optional package, so that once it is null will throw an exception.
//empty方法的使用
Optional<Car> optCar = Optional.empty();
//of方法的使用
Optional<Car> optCar = Optional.of(car);
//ofNullable方法的使用
Optional<Car> optCar = Optional.ofNullable(car);
复制代码
- Value of a field value you can use the map method Optional object from its package in;
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
复制代码
- If continuous, progressive layers to obtain the value of an object field from the end of the chain, you can not use all the map method, need to use a flatMap, and finally use the map method;
//转换之前
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
//转换后
public String getCarInsuranceName(Optional<Person> person) {
return person.flatMap(Person::getCar)
.flatMap(Car::Insurance)
.map(Insurance::getName)
.orElse("Unknown");
}
复制代码
- Optional in the map, flatMap filter method, the concept of the method is very similar to the corresponding Stream, Optional difference is at most one of the elements, considered a special case of Stream - a special set.
- Do not use ifPresent and get methods, and they are essentially not applicable Optional objects before the same pattern, are bloated determines if-then-else statements;
- Since Optional can not be serialized, so in the domain model, could not be defined as a field Optional, because: Optional is designed to support only able to return Optional object syntax, if we want to introduce Optional in the domain model, this alternative may be by the following method:
public class Person {
private Car car;
public Optional<Car> getCarAsOptional() {
return Optional.ofNullable(car);
}
}
复制代码
- Do not use the underlying type Optional object because: Optional base type of object does not support the map, flatMap and filter methods, and these methods are Optional very powerful way.
Real case
Case 1: Using the tools improved method might throw an exception API
There are two ways to handle exceptions Java method results: Returns null (or error code); throws an exception, for example: Integer.parseInt (String) This method - if not resolved to the corresponding integer, which throws a NumberFormationException, in which case we will generally use try / catch statement to handle exceptions.
We generally recommend the try / catch block to a single extraction method, this method is used here Optional design, as follows. In a development, you may attempt to build a OptionalUtility tools, these complex try / catch logic encapsulated.
public static Optional<Integer> stringToInt(String a) {
try{
return Optional.of(Integer.parseInt(s));
} catch (NumberFormationException e) {
return Optional.empty();
}
}
复制代码
Case 2: Integrated Case
Now there is a method, it is to try to obtain a value corresponding to a keyword from an attribute mapping, the following sample code:
public static int readDuration(Properties properties, String name) {
String value = properties.getProperty(name);
if (value != null) {
try {
int i = Integer.parseInt(value);
if (i > 0) {
return i;
}
} catch (NumberFormatException e) {
}
}
return 0;
}
复制代码
Optional wording after use, the code is as follows:
public static int readDurationWithOptional(Properties properties, String name) {
return Optional.ofNullable(properties.getProperty(name))
.flatMap(OptionalUtility::stringToInt)
.filter(integer -> integer > 0)
.orElse(0);
}
复制代码
If the attribute values require access does not exist, the return value Properites.getProperty (String) method is a null, the method can be used noNullable plant to convert the value Optional objects; Next, flatMap can be converted to a Optional Optional objects ; finally filtered using filter negative, then you can use orElse getting a property value, a default value is returned if the get 0.
to sum up
Optional use the same ideas and Stream, is a chain of ideas, with database queries like, express very strong, but also eliminates the need for complex which try / catch and if-then-else approach. Later developed may be used Optional design API, allowing to design a more secure interfaces and methods.
This focus on the number of back-end technology, JVM troubleshooting and optimization, Java interview questions, personal growth and self-management, and other topics, providing front-line developers work and growth experience for the reader, you can expect to gain something here.