map() và flatMap() là 2 khái niệm được Java vay mượn từ functional languages. Trong Java 8, chúng ta có thể tìm thấy chúng trong Optional , Stream và CompletableFuture.
Map và FlatMap trong Optional
map() method sử dụng để chuyển một Optional của Object này sang Object khác có thể cùng kiểu dữ liêu.
Optional<String> s = Optional.of("test"); Optional<Integer> r = s.map(String::length);
Tuy nhiên, với cấu trúc lồng
Optional<Optional<String>> s = Optional.of(Optional.of("test"));
Chúng ta cần sử dụng đến flatMap() để làm phẳng dữ liệu.
Optional<Optional<String>> s = Optional.of(Optional.of("test")); Optional<Integer> size = s.flatMap(q -> q).map(String::length);
Như ví dụ trên, flatMap() để giúp chúng ta chuyển Optional lồng bên trong một Optional khác sang Optional<String> cấu trúc phẳng, từ đó chúng ta có thể sử dụng map() để có được kết quả tương tự.
Map() và FlatMap() trong Stream
Cả 2 method đều hoạt động như nhau trong Optional và Stream.
Giả sử có User class chứa một List<String> subject.
public class User { private String name; private int age; List<String> subjects; // constructor, getter, setter }
Khi có một Stream<User>, chúng ta muốn lấy Stream<String> subject tổng hợp từ tất cả các User. Mỗi phần tử trong Stream<User> chúng ta có thể tạo ra 1 Stream<Subject>, vậy một Stream<User> chúng ta sẽ có Stream<Stream<String>>. Sử dụngflatMap()để làm phẳng dữ liệu từ Stream<Stream<String>> sang Stream<Stream>.
public class test { public static void main(String[] agrs) { List<User> users = Arrays.asList(new User("user 1", 12, Arrays.asList("A", "B")), new User("user 2", 15, Arrays.asList("C", "D")), new User("user 3", 12, Arrays.asList("E"))); List<String> subjects = users.stream() .flatMap(user -> user.getSubjects().stream()).collect(Collectors.toList()); } }
Trong khi map() chỉ có tác dụng chuyển từ một Strean<R> sang Strean<T> khác.
public class test { public static void main(String[] agrs) { List<User> users = Arrays.asList(new User("user 1", 12, Arrays.asList("A", "B")), new User("user 2", 15, Arrays.asList("C", "D")), new User("user 3", 12, Arrays.asList("E"))); List<String> names = users.stream() .map(user -> user.getName()) .collect(Collectors.toList()); } }
Tóm lược
Như vậy là chúng ta đã tìm hiểu về điểm khác nhau giữa map() và flatMap(), cả 2 method này được sử dụng khá nhiều từ Java 8 trở đi với sự phổ biến của Stream API. flatMap() sẽ rất hữu ích khi chúng ta muốn chuyển đổi một Stream<<Stream<R>> sang Stream<T>.
Nguồn tham khảo