Dưới đây là một số biến thể về câu trả lời của Sotirios Delimanolis , khá hay khi bắt đầu bằng (+1). Hãy xem xét những điều sau đây:
static <X, Y, Z> Map<X, Z> transform(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
return input.keySet().stream()
.collect(Collectors.toMap(Function.identity(),
key -> function.apply(input.get(key))));
}
Một vài điểm ở đây. Đầu tiên là việc sử dụng các ký tự đại diện trong các tổng quát; Điều này làm cho chức năng có phần linh hoạt hơn. Ví dụ, một ký tự đại diện sẽ là cần thiết nếu bạn muốn bản đồ đầu ra có một khóa đó là siêu lớp của khóa bản đồ đầu vào:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(Ngoài ra còn có một ví dụ cho các giá trị của bản đồ, nhưng nó thực sự bị chiếm đoạt và tôi thừa nhận rằng việc có ký tự đại diện giới hạn cho Y chỉ giúp ích trong các trường hợp cạnh.)
Điểm thứ hai là thay vì chạy luồng trên bản đồ đầu vào entrySet
, tôi đã chạy nó qua keySet
. Điều này làm cho mã sạch hơn một chút, tôi nghĩ, với chi phí phải lấy các giá trị ra khỏi bản đồ thay vì từ mục nhập bản đồ. Ngẫu nhiên, ban đầu tôi đã có key -> key
đối số đầu tiên toMap()
và điều này đã thất bại với một lỗi suy luận kiểu vì một số lý do. Thay đổi nó để (X key) -> key
làm việc, như đã làm Function.identity()
.
Một biến thể khác như sau:
static <X, Y, Z> Map<X, Z> transform1(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
Map<X, Z> result = new HashMap<>();
input.forEach((k, v) -> result.put(k, function.apply(v)));
return result;
}
Điều này sử dụng Map.forEach()
thay vì các luồng. Điều này thậm chí còn đơn giản hơn, tôi nghĩ, bởi vì nó phân phối với các nhà sưu tập, có phần vụng về để sử dụng với bản đồ. Lý do là Map.forEach()
cung cấp khóa và giá trị dưới dạng tham số riêng biệt, trong khi luồng chỉ có một giá trị - và bạn phải chọn sử dụng khóa hoặc mục nhập bản đồ làm giá trị đó. Về mặt trừ, điều này thiếu đi sự tốt đẹp, phong phú của các phương pháp khác. :-)
e -> e.getKey()
bằngMap.Entry::getKey
. Nhưng đó là vấn đề của hương vị / phong cách lập trình.