Mục lục
Map là một trong những cấu trúc dữ liệu được sử dụng nhiều bậc nhất trong các ngôn ngữ lập trình nói chung và Java nói riêng. Trong bài viết này chúng ta sẽ tìm hiểu cách khởi tạo một Map instance, ứng với mỗi cách sẽ được sử dụng trong các trường hợp cụ thể.
Static block
Chúng ta có thể khởi tạo một HashMap thông qua static block như sau
import java.util.HashMap; import java.util.Map; public class Main { public static Map<Integer, String> map; static { map= new HashMap<>(); map.put(1, "Hai"); map.put(2, "Hieu"); } public static void main(String[] args) { for (Map.Entry<Integer, String> item : map.entrySet()) { System.out.println("Key: " + item.getKey() + " - " + "Value: " + item.getValue()); } } }
Output
Key: 1 - Value: Hai Key: 2 - Value: Hieu
Với cách khởi tạo này chúng ta có thể sử dụng để khởi tạo một HashMap có tập giá trị được xác định sẵn.
Ngoài ra chúng ta còn có thể khởi tạo HashMap thông qua double-brace syntax:
public class Main { public static Map<Integer, String> map = new HashMap<>() {{ put(1, "Hai"); put(2, "Hieu"); }}; ... }
Thông thường cách này thường không được khuyến khích sử dụng bởi vì bên dưới nó sẽ tạo ra một anonymous class và khởi tạo một instance từ đó. Việc này có thể dẫn đến tình trạng memory leak khi chúng ta sử dụng cách này quá ở quá nhiều nơi trong ứng dụng.
Java collections
Nếu chúng ta muốn tạo ra một singleton immutable map chỉ chứa duy nhất một phần tử thì có thể sử dụng Collections.singletonMap().
import java.util.Collections; import java.util.Map; public class Main { public static void main(String[] args) { Map<Integer, String> map = createSingletonMap(); for (Map.Entry<Integer, String> item : map.entrySet()) { System.out.println("Key: " + item.getKey() + " - " + "Value: " + item.getValue()); } } public static Map<Integer, String> createSingletonMap() { return Collections.singletonMap(1, "Hai"); } }
Output
Key: 1 - Value: Hai
Lưu ý rằng HashMap instance được tạo ra từ Collections.singletonMap(), nếu chúng ta cố gắng thêm hoặc xóa phần tử trong nó thì sẽ gây ra UnsupportedOperationException.
Khởi tạo HashMap trong Java 8
Trong Java 8 chúng ta có thể sử dụng Stream API để khởi tạo map.
Collectors.groupingBy()
Gỉa sử chúng ta có class User sau.
class User { private Integer id; private String name; private Integer age; // getter, setter, constructor }
Đặt trường hợp mình có một List các user và mình muốn nhóm user lại theo độ tuổi thì chúng ta có thể sử dụng groupingBy() method như sau
public class Main { public static void main(String[] args) { List<User> users = new ArrayList<>(); users.add(new User(1, "Hai", 21)); users.add(new User(2, "Hieu", 21)); users.add(new User(3, "Ha", 23)); Map<Integer, List<User>> map = groupUserById(users); for(Map.Entry<Integer, List<User>> item : map.entrySet()) { System.out.println("Age: " + item.getKey()); System.out.println("User count: " + item.getValue().size()); } } public static Map<Integer, List<User>> groupUserById(List<User> users) { return users.stream().collect(Collectors.groupingBy(User::getAge)); } }
Output
Age: 21 User count: 2 Age: 23 User count: 1
Collectors.toMap()
Tương tự với cách sử dụng của groupingBy(), toMap() được sử dụng trong trường hợp Map.value không phải là một kiểu dữ liệu dạng collection như List, Set v.v
public class Main { public static void main(String[] args) { String[][] strs = new String[][] { { "Hello", "World" }, { "John", "Doe" }}; Map<String, String> map = toMap(strs); for(Map.Entry<String, String> item : map.entrySet()) { System.out.println("Key: " + item.getKey() + " - " + "Value: " + item.getValue()); } } public static Map<String, String> toMap(String[][] strs) { return Stream.of(strs).collect(Collectors.collectingAndThen( Collectors.toMap(data -> data[0], data -> data[1]), Collections::<String, String> unmodifiableMap)); } }
Output
Key: Hello - Value: World Key: John - Value: Doe
Khởi tạo Map trong Java 9
Java 9 ra mắt với nhiều factory method trong Map interface cho phép chúng ta khởi tạo các immutable map như sau:
Map.of()
Factory method này có thể nhận một cặp tham số cho single map, nhiều cặp tham số cho một map bình thường chứa nhiều phần tử hoặc có thể không nhận bất kỳ một tham số nào để khởi tạp empty map.
Map<String, String> emptyMap = Map.of(); Map<String, String> singletonMap = Map.of("key1", "value"); Map<String, String> map = Map.of("key1","value1", "key2", "value2");
Nhưng xin hãy lưu ý rằng Map.of() chỉ hỗ trợ tối đa 10 cặp key-value.
Map.ofEntries()
Tương tự như Map.of() tuy nhiên Map.ofEntries() không giới hạn số lượng cặp key-value truyền vào.
Map<String, String> map = Map.ofEntries( new AbstractMap.SimpleEntry<String, String>("name", "John"), new AbstractMap.SimpleEntry<String, String>("city", "budapest"), new AbstractMap.SimpleEntry<String, String>("zip", "000000"), new AbstractMap.SimpleEntry<String, String>("home", "1231231231") );
Lưu ý rằng Map.ofEntries() và Map.of() sẽ tạo ra các immutable map cho nên chúng ta không thể chỉnh sửa nó sau khi đã khởi tạo. Để khởi tạo map thông qua những method này và chỉnh sửa nó về sau thì chúng ta có thể sử bao bên ngoài nó một Map implement như HashMap như sau:
Map<String, String> map = new HashMap<String, String> ( Map.of("key1","value1", "key2", "value2")); Map<String, String> map2 = new HashMap<String, String> ( Map.ofEntries( new AbstractMap.SimpleEntry<String, String>("name", "John"), new AbstractMap.SimpleEntry<String, String>("city", "budapest")));
Tóm lược
Qua bài viết trên chúng ta đã được giới thiệu một số cách khởi tạo Map và HashMap trong Java. Hãy lưu ý rằng immutable map sau khi khởi tạo thì chúng ta không thể chỉnh sửa nó nếu không sẽ gây ra các exception không đáng có.
Nguồn tham khảo