0

Optional và một số hàm sử dụng trong Java

Giả sử bạn tham gia một lớp giới thiệu về Java và đạt 90 và 100 điểm trong 2 bài kiểm tra đầu. Có một câu hỏi giành cho bạn: “Trung bình của bạn là bao nhiêu?”. Giá trị trung bình được tính như sau: (90+100)/2 = 95. Tuyệt! Tiếp tục, giả sử bạn tham gia lớp học Java thứ 2, và đây là ngày đầu tiên, chúng tôi tiếp tục hỏi bạn về điểm trung bình. Bạn chưa làm bài kiểm tra nào cả, và bạn không có gì để tính giá trị trung bình. Chính xác giá trị trung bình của bạn là 0, nghe có vẻ tệ nhưng đó là sự thật, chỉ đơn giản là không có data và dĩ nhiên không có giá trị trung bình.
Vậy làm sao chúng ta có thể thể hiện câu trả lời rằng: “Tôi không biết”, hay “không áp dụng” trong Java? Bắt đầu Java 8, chúng ta sử dụng Optional. Bạn có thể có một Optional rỗng hoặc chuyển value vào trong Optional, đơn giản chỉ cần nghĩ Optional như một cái hộp có thể có cái gì trong đó, nhưng cũng có thể trống.
Sau đâu là đoạn code cách tính giá trị trung bình ở trên:

public static Optional<Double> average(int… scores) {
    if (scores.length == 0) return Optional.empty(); 
    int sum = 0;
    for (int score: scores) sum += score;
    return Optional.of((double) sum / scores.length);
}

Bây giờ chúng ta xem những gì có bên trong 2 chiếc hộp:

System.out.println(average(90, 100)); // Optional[95.0]
System.out.println(average()); // Optional.empty

Bạn có thể thấy một Optional chứa value và một Optional trống rỗng. Thông thường, muốn check một Optional có value hay không và lấy nó ra:

Optional<Double> opt = average(90, 100);
if (opt.isPresent())
    System.out.println(opt.get()); // 95.0

Hàm isPresent() sẽ check xem Optional có value hay không.
Hàm get() sẽ lấy giá trị bên trong Optional. Và khi Optional không có giá trị thì sẽ xảy ra exception khi lấy value: java.util.NoSuchElementException: No value present.
Thông thường, khi tạo một Optional, nếu value = null thì chúng ta sẽ tạo một empty Optional. Đơn giản như sau:
Optional o = (value== null) ? Optional.empty(): Optional.of(value);
Khi nó trở thành một loại pattern phổ biến, Java đã cho chúng ta một hàm để làm điều tương tự:
Optional o = Optional.ofNullable(value);
Method trên là một static method chúng ta cần biết về Optional. Bảng dưới đây liệt kê một số instance method khác của Optional:

Chúng ta đã biết về method get() và isPresent(). Method khác cho chúng ta viết code sử dụng Optional trên một dòng, khá là dễ đọc. Thay vì sử dụng lệnh if, chúng ta sử dụng check giá trị trung bình trước, ta có thể chỉ định một Consumer run bên trong Optional khi nó có value, còn không, thì không cần làm gì cả. Bằng cách dùng method ifPresent() chúng ta có thể làm như sau:

Optional<Double> opt = average(90, 100);
opt.ifPresent(System.out::println);

Cũng có một số method khác cho phép chúng ta chỉ định những gì cần làm khi Optional không có value:

30: Optional<Double> opt = average();
31: System.out.println(opt.orElse(Double.NaN));
32: System.out.println(opt.orElseGet(() -> Math.random()));
33: System.out.println(opt.orElseThrow(() -> new IllegalStateException()));

Và đây là kết quả:

NaN
0.49775932295380165
Exception in thread "main" java.lang.IllegalStateException
at optional.Average.lambda$3(Average.java:56)
at optional.Average$$Lambda$5/455659002.get(Unknown Sour
at java.util.Optional.orElseThrow(Optional.java:290)

Dòng 31 thể hiện chúng ta có thể trả ra một giá trị hoặc một biến khi Optional rỗng.
Dòng 32 thể hiện sử dụng một Supplier để tạo ra value và return nó.
Dòng 33 thì sử dụng một Supplier khác tạo ra exception mà nó nên được throw.
Nhớ rằng 2 mehthod lấy Supplier khác tên. Bạn có thấy vì sao đoạn code dưới đây không thể compile?

System.out.println(opt.orElseGet(
() -> new IllegalStateException())); // DOES NOT COMPILE

Đơn giản, opt là một Optional<Double>, điều đó có nghĩa Supplier phải return ra kiểu Double, khi nó là một exception, dĩ nhiên type của nó sẽ hoàn toàn sai.
Còn nếu trong trường hợp có value, những hàm trên sẽ return ra value, không cần dùng đến logic “orElse”.
=>> Thế thì Optional có giống null?
Trước Java 8, chúng ta sẽ return ra null thay vì dùng Optional. Đó là một cách thể hiện không rõ ràng vì null có thể là một giá trị đặc biệt. NGược lại, return ra một Optional là một cách hoàn toàn rõ ràng để chỉ ra rằng API có thể không có giá trị trong đó.
Một số tác dụng khác là bạn có thể sử dụng kiểu Functional Programming với ifPresent() và một số method khác hơn là cần phải sử dụng lệnh if. :>>

=> Bài viết tham thảo từ cuốn "OCP Oracle Certified Professional Java SE 8 Programmer II Study Guide Exam 1Z0-809". Mong rằng bài viết trên sẽ giúp ích cho các bạn trong việc sử dụng Optional trong java.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí