2015-06-16 19 views
75

Sự khác biệt giữa hai phương thức sau: Optional.flatMap() và Optional.map() là gì?Java 8 - Sự khác biệt giữa Optional.flatmap và Optional.map

Ví dụ sẽ được đánh giá cao.

+1

Xem http://stackoverflow.com/questions/26684562/java-8-map-and-flatmap-methods –

+2

@AlexisC. Liên kết của bạn là về bản đồ của Stream và flatMap, không phải Tùy chọn. – Eran

+0

từ tài liệu java: Nếu có giá trị, hãy áp dụng hàm ánh xạ mang tùy chọn được cung cấp cho nó, trả về kết quả đó, nếu không trả về một tùy chọn rỗng. Phương pháp này tương tự như bản đồ (Chức năng), nhưng trình ánh xạ được cung cấp là một bản đồ có kết quả là tùy chọn và nếu được gọi, flatMap không bao bọc nó với tùy chọn bổ sung. – griFlo

Trả lời

64

Sử dụng map nếu hàm trả về đối tượng bạn cần hoặc flatMap nếu hàm trả về Optional. Ví dụ:

public static void main(String[] args) { 
    Optional<String> s = Optional.of("input"); 
    System.out.println(s.map(Test::getOutput)); 
    System.out.println(s.flatMap(Test::getOutputOpt)); 
} 

static Optional<String> getOutputOpt(String input) { 
    return input == null ? Optional.empty() : Optional.of("output for " + input); 
} 

static String getOutput(String input) { 
    return input == null ? null : "output for " + input; 
} 

Cả hai báo cáo in đều giống nhau.

+1

Câu hỏi: sẽ '[phẳng] Bản đồ' có bao giờ gọi hàm ánh xạ với' đầu vào == null' không? Sự hiểu biết của tôi là các tùy chọn 'Tùy chọn' nếu nó vắng mặt - [JavaDoc] (https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#flatMap-java.util.function .Function-) có vẻ như ngược lại điều này - "_Nếu một giá trị có mặt, áp dụng ..._". –

+0

@BoristheSpider Optional.of (null)! = Optional.empty() –

+4

@DiegoMartinoia 'Optional.of (null)' là một 'Ngoại lệ '. 'Optional.ofNullable (null) == Optional.empty()'. –

34

Cả hai đều có chức năng từ loại tùy chọn cho một thứ gì đó.

Bản đồ áp dụng chức năng "nguyên trạng" trên không bắt buộc bạn phải:

if (optional.isEmpty()) return Optional.empty(); 
else return Optional.of(f(optional.get())); 

gì xảy ra nếu chức năng của bạn là một hàm từ T -> Optional<U>? Kết quả của bạn bây giờ là Optional<Optional<U>>!

Đó là những gì flatMap là về: nếu hàm của bạn đã trả về một Optional, flatMap thì thông minh hơn một chút và không gấp đôi, trả lại Optional<U>. Đó là thành phần của hai thành ngữ chức năng: mapflatten.

4

Lưu ý: - bên dưới là minh họa về bản đồ và chức năng bản đồ phẳng, nếu không Tùy chọn được thiết kế chủ yếu chỉ được sử dụng làm loại trả lại.

Như bạn đã biết Tùy chọn là một loại chứa có thể hoặc không chứa một đối tượng duy nhất, vì vậy nó có thể được sử dụng ở bất kỳ nơi nào bạn dự đoán giá trị rỗng (Bạn có thể không bao giờ thấy NPE nếu sử dụng Tùy chọn đúng cách). Ví dụ nếu bạn có một phương pháp mà hy vọng một đối tượng người có thể được nullable bạn có thể muốn viết phương pháp một cái gì đó như thế này:

void doSome(Optional<Person> person){ 
    /*and here you want to retrieve some property phone out of person 
    you may write something like this: 
    */ 
    Optional<String> phone = person.map((p)->p.getPhone()); 
    phone.ifPresent((ph)->dial(ph)); 
} 
class Person{ 
    private String phone; 
    //setter, getters 
} 

đây bạn đã trở lại một kiểu String mà được tự động được bọc trong một loại bắt buộc.

Nếu người lớp trông như thế này, ví dụ: điện thoại cũng là bắt buộc

class Person{ 
    private Optional<String> phone; 
    //setter,getter 
} 

Trong trường hợp này gọi chức năng bản đồ sẽ quấn giá trị trả về trong Tùy chọn và mang lại một cái gì đó như:

Optional<Optional<String>> 
//And you may want Optional<String> instead, here comes flatMap 

void doSome(Optional<Person> person){ 
    Optional<String> phone = person.flatMap((p)->p.getPhone()); 
    phone.ifPresent((ph)->dial(ph)); 
} 

PS; Không bao giờ gọi phương thức get (nếu bạn cần) trên một tùy chọn mà không kiểm tra nó với isPresent() trừ khi bạn không thể sống mà không có NullPointerExceptions.

+0

Tôi nghĩ rằng ví dụ này có khả năng phân tâm từ bản chất của câu trả lời của bạn bởi vì lớp của bạn 'Person' là lạm dụng' Tùy chọn'. Nó là trái với ý định của API để sử dụng 'Tùy chọn' trên các thành viên như thế này - xem http://mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003274.html – 8bitjunkie

+0

@ 8bitjunkie Cảm ơn bạn đã chỉ mà ra, nó khác với tùy chọn của Scala .. – SandeepGodara

0

Sử dụng flatMap cho hàm trả về đối tượng. Nó kết hợp hai hoặc nhiều tùy chọn cho một cái duy nhất mà nó làm phẳng nó.

Sử dụng Sơ đồ để có được đơn Tùy chọn

Eg: Class Student { 
     private Optional<Teacher> classTeacher; 
     private Optional<String> name; 
     private String adminNumber; } 

    Class Teacher { 
     private Optional<String> name; 
    } 

To get the class teacher from Student use flat map. To get Teacher name from Teacher Object Use map. 
Các vấn đề liên quan