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