preface
Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”. Optional is a new feature introduced in Java 8. It is designed to help programmers with NPE (NullPointerException) issues. However, many people use it in their projects because it is readable. Else, in my opinion, since Optional has been launched, it must have the value and significance to use it, it is necessary to learn to understand it, after master to write elegant and slightly advanced sense of code! Hopefully Optional will be an Option in your coding process.
introduce
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
Optional is a container object that may or may not contain non-null values. Essentially, it is a wrapper class that holds values of any specific Java type that can be retrieved using the GET method.
Static method to create an instance
Optional.empty()
- To create an empty Optional instance
System.out.println(Optional.empty()); // Optional.empty
Copy the code
Optional.of(T value)
-
Creates an Optional instance with the specified current non-null value
-
Notice that the value passed in is not null; otherwise, NPE is reported
The sample
// The object property is null, not null
User emptyUser = new User();
System.out.println(Optional.of(emptyUser));
// The User object is empty
User nullUser = null;
System.out.println(Optional.of(nullUser)); // throw NullPointerException
// The String object is empty
String nullString = null;
System.out.println(Optional.of(nullString)); // // throw NullPointerException
Copy the code
Optional.ofNullable(T value)
- Returns Optional describing the specified value if the value is non-empty, otherwise returns option.empty () without raising an exception
The sample
// The object property is null, not null
User emptyUser = new User();
System.out.println(Optional.ofNullable(emptyUser)); // Optional[User{id=null, name='null', sex='null', age=null, salary=null}]
// The User object is empty
User nullUser = null;
System.out.println(Optional.ofNullable(nullUser)); // Optional.empty
// The String object is empty
String nullString = null;
System.out.println(Optional.ofNullable(nullString)); // Optional.empty
Copy the code
summary
-
Before using Optional, you need to create instances using the above three static methods
-
Create an empty instance using option.empty ()
-
If you want to create a non-null instance, you are advised to use optional.ofNullable (). If you can specify that the parameter is not null, you can use option.of ().
Common instance methods
isPresent()
- Used to determine whether the wrapper value exists, returning true if it does, false otherwise
The sample
Optional<User> opt1 = Optional.of(emptyUser); // Optional[User{id=null, name='null', sex='null', age=null, salary=null}]
Optional<User> opt2 = Optional.ofNullable(nullUser); // Optional.empty
System.out.println(opt1.isPresent() ? "Package value exists" : "Package value does not exist"); // The package value exists
System.out.println(opt2.isPresent() ? "Package value exists" : "Package value does not exist"); // The package value does not exist
Copy the code
ifPresent(Consumer<? super T> consumer)
- If the Optional instance has a value, call the function object consumer for it; otherwise, no action is taken
How to understand the functional interface Consumer?
// Consumer methods
private static void consumerMethod(User user, Consumer<User> cu) {
cu.accept(user);
}
// main called in the main method
User user01 = new User(42."Shi Tiangou"."Female".16.4520);
consumerMethod(user01, user1 -> System.out.println(user1.getName() + user1.getSex())); // Shi Tiangou female
Copy the code
A Consumer is a Consumer interface that receives a snippet of interface code or a Lambda expression. The common method is the Accept () method, an abstract method that consumes a value passed in without returning a value. Consume functions (or snippets of code) and encapsulate logical code.
The sample
// Opt1 and opt2 are defined above
opt1.ifPresent(System.out::println); // User{id=null, name='null', sex='null', age=null, salary=null}
opt2.ifPresent(System.out::println); // There is no output
Copy the code
get()
- If the wrapper value exists, it is taken from the Optional wrapper and returned, otherwise NoSuchElementException is thrown
The sample
User user = opt1.get();
opt2.get(); // throw NoSuchElementException: No value present
System.out.println(user); // User{id=null, name='null', sex='null', age=null, salary=null}
Copy the code
orElse(T other)
- Return this value if it exists, otherwise return other
The sample
User user02 = new User(20."Bill"."Female".15.2350);
Opt2 is null, so return other => user02
User orElse = opt2.orElse(user02);
System.out.println(orElse); / / User {id = 20, name = 'bill', sex = 'female' and age = 15, salary = 2350}
Copy the code
orElseGet(Supplier<? extends T> other)
- Return the value if it exists, otherwise call other and return the result of the call. The Supplier parameter receives the implementation of the Supplier interface. Optional returns the value if it contains a value, otherwise the return value is retrieved from the Supplier
How do I understand the functional interface Supplier?
// Provider/vendor approach
private static User supplierMethod(Supplier<User> su) {
return su.get();
}
// main called in the main method
User user03 = new User(42."Pockmarked seed"."Male".29.4000);
System.out.println(supplierMethod(() -> user03)); / / User {id = 42, name = 'just soso' sex = 'male', the age = 29, salary = 4000}
Copy the code
Supplier is a provider interface that receives interface code snippet or Lambda expression. The general method is to use get() method. This abstract method gets the result of whatever data is passed in. Functions (or code snippets) are provided and logical code is encapsulated.
The sample
orElseThrow(Supplier<? extends X> exceptionSupplier)
- Returns the included value, if present, otherwise throws the exception created by exceptionSupplier
The sample
try {
// opt2 is null, so the provided exception is thrown
User elseThrow = opt2.orElseThrow(NullPointerException::new);
System.out.println(elseThrow);
}catch (Exception e) {
System.out.println(e); // java.lang.NullPointerException
}
Copy the code
filter(Predicate<? super T> predicate)
- If the wrapper value exists and matches the predicate conditions, an Optional describing the value is returned, otherwise Optional. Empty is returned
The sample
Optional<User> opt = Optional.ofNullable(user02)
.filter(u2 -> u2.getSalary() > 6000);
// Conditions for the predicate do not meet
System.out.println(opt); // Optional.empty
Copy the code
map(Function<? super T,? extends U> mapper)
Source code analysis
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if(! isPresent())return empty();
else {
returnOptional.ofNullable(mapper.apply(value)); }}Copy the code
- If a value exists, the application provides a mapping function to it that returns an Optional wrapped in option.ofNullable
The sample
Integer newNameLens =
Optional.of(user03) // Optional<User>
.map(u3 -> u3.getName() + The '-' + u3.getSex()) // This returns Optional
.map(newName -> newName.trim()) // This returns Optional
.map(newName -> newName.length()) // This returns Optional
.get(); // Fetch the value wrapped in Optional
System.out.println("New name length after Map processing:" + newNameLens); // After the Map processing, get the new name length: 5
Copy the code
flatMap(Function<? super T,Optional> mapper)
Source code analysis
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if(! isPresent())return empty();
else {
returnObjects.requireNonNull(mapper.apply(value)); }}Copy the code
- If a value exists, apply a mapping function to it, which returns an Optional wrapped in objects.requirenonNULL. If the mapping function is null, the NPE is reported
The sample
user02.setName("Zhuge power");
String firstName = Optional.ofNullable(user02) // // returns Optional
.flatMap(u2 -> Optional.of(u2.getName())) // This returns Optional
.flatMap(name -> {
String familyName;
if (name.length() <=3) {
familyName = name.substring(0.1);
} else {
familyName = name.substring(0.2);
}
return Optional.of(familyName);
}) // This returns Optional
System.out.println("User name and last name after flatMap processing:" + firstName); / / various ge
Copy the code
summary
-
Whenever a wrapper value exists, you get the Optional that describes the value
-
Use static ofNullable() when creating Optional wrapper classes with orElse at the end of the chain. In addition, isPresent() can be used to declare null and ifPresent() to consume the possible wrapper value. In this case, it does not matter if the value is null, and NPE will not be processed and reported
-
The Optional instance method map() differs from flatMap() in that one mapping function results in a concrete value and can be null, while the latter is Optional and cannot be null otherwise NPE arrangements
Scenario using
A null value transformation
String avatarUrl = null;
User user = new User("HUALEI", url);
String userAvatarUrl = Optional.ofNullable(user)
.map(u -> u.getUserAvatar()).orElse("https://p3-passport.byteacctimg.com/img/user-avatar/7c53d8cf8b3f3de699f1db654b88063d~300x300.image");
user.setUserAcatar(avatarUrl);
Copy the code
If no profile picture is set, the default profile picture is used.
Integer salary = Optional.ofNullable(emptyUser)
.map(u -> u.getSalary())
.orElse(0);
emptyUser.setSalary(salary);
Copy the code
If the employee does not have an initial salary, it defaults to 0.
Value to filter
Verify the mobile phone number format, written as follows:
String phone = "12345678910";
String regex = "^ ([0-9] (13) | | (14 [5] | 7) (15 ([0, 3] | [5-9])) | | (17 [013678]) (18 [0, 5-9])) \ d {8} $";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(phone);
boolean isMatch = m.matches();
if(isMatch){
System.out.println("Correct format of mobile phone number");
} else {
System.out.println("Mobile phone number format error");
}
Copy the code
Filter using the option.filter () method
boolean isValid = Optional.ofNullable(user)
.filter(u -> {
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(u.getPhone()).matches();
})
.isPresent();
assertTrue(isValid);
Copy the code
Mixed operation
Employees list
User user01 = new User(42."Shi Tiangou"."Female".16.4520);
User user02 = new User(20."Bill"."Female".15.2350);
User user03 = new User(42."Pockmarked seed"."Male".29.4000);
List<User> users = new ArrayList<User>() {{
add(user01);
add(user02);
add(user03);
}};
Copy the code
To find the total salary of the employees, we might have written this before:
// Calculate the salary accumulator
int sumSalary = 0;
// Add up the salary of each non-empty user in the enhanced for loop
if(users ! =null) {
for (User u : users) {
if(u ! =null) {
sumSalary += u.getSalary();
}
}
}
System.out.println("Total employee salary:" + sumSalary); // Total employee salary: 10870
Copy the code
If you read the functional operations on the stream – juejin (cn), you might write something like this:
Integer sumSalary = 0;
if(users ! =null) {
sumSalary = users.stream()
.filter(Objects::nonNull)
.map(User::getSalary)
.reduce(0, (sum, currentValue) -> sum + currentValue);
}
System.out.println("Total employee salary:" + sumSalary); // Total employee salary: 10870
Copy the code
But would you write that?
Integer sumSalary = Optional.ofNullable(users).map(us -> {
Integer sum = 0;
for (User user : us) {
sum += Optional.ofNullable(user).map(User::getSalary).orElse(0);
}
return sum;
}).orElse(0);
System.out.println("Total employee salary:" + sumSalary); // Total employee salary: 10870
Copy the code
At the end
Writing is not easy, welcome everyone to like, comment, your attention, like is my unremitting power, thank you to see here! Peace and Love.