2016-03-01 18 views
5
Map<String, String> map1 = new HashMap<>(); 
map1.put("k1", "v1"); 
map1.put("k2", "v2"); 
map1.put("k3", "v3"); 

Map<String, String> map2 = new HashMap<>(); 
map2.put("v1", "val1"); 
map2.put("v2", "val2"); 
map2.put("v3", "vav3"); 

Tôi muốn cập nhật giá trị của map1 để nó có mục:giá trị cập nhật trong Bản đồ trên cơ sở bản đồ khác trong Java

  • "k1", "VAL1",
  • "k2", "VAL2",
  • "k3", "val3"

giải pháp của tôi:

01.
for (Map.Entry<String, String> entry : map1.entrySet()) { 
    map1.put(entry.getKey(), map2.get(entry.getValue())); 
} 

Có cách nào tốt hơn để thực hiện việc này không?

Edit: Tôi đang sử dụng Java 7 nhưng tò mò muốn biết nếu có bất kỳ cách nào tốt hơn trong Java 8.

+0

Không thực sự, không - mặc dù có vẻ như bạn nên làm 'map3.put' thay vì' map1.put'? –

+1

là java 8 này? trong trường hợp đó, các luồng có thể giúp bạn. – njzk2

+0

Ngoài ra, bạn nên làm 'map2.put' thay vì' map1.put' khi điền vào 'map2'. – Atri

Trả lời

3

Bắt đầu với Java 8, bạn có thể chỉ có

map1.replaceAll((k, v) -> map2.get(v)); 

replaceAll(function) sẽ thay thế tất cả các giá trị từ bản đồ map1 bằng kết quả của việc áp dụng hàm đã cho. Trong trường hợp này, hàm chỉ truy xuất giá trị từ map2.

Lưu ý rằng giải pháp này có cùng vấn đề với mã ban đầu của bạn: nếu map2 không có ánh xạ tương ứng, null sẽ được trả lại. Bạn có thể muốn gọi getOrDefault để có giá trị mặc định trong trường hợp đó.

public static void main(String[] args) { 
    Map<String, String> map1 = new HashMap<>(); 
    map1.put("k1", "v1"); 
    map1.put("k2", "v2"); 
    map1.put("k3", "v3"); 

    Map<String, String> map2 = new HashMap<>(); 
    map2.put("v1", "val1"); 
    map2.put("v2", "val2"); 
    map2.put("v3", "val3"); 

    map1.replaceAll((k, v) -> map2.get(v)); 

    System.out.println(map1); // prints "{k1=val1, k2=val2, k3=val3}" 
} 
+0

Bất kỳ bình luận nào cho Java 7? –

+0

@dev ツ Thành thật mà nói, ngoài trường hợp tôi đã đề cập (bản đồ không có khóa tương ứng), không có chỗ để cải thiện. Nó là tốt như nó được. – Tunaki

0

trong Java 8 bạn có thể viết:

map1.entrySet() 
    .stream() 
    .map(entry -> new SimpleEntry(entry.getKey(), map2.get(entry.getValue()))) 
    .collect(Collectors.toMap(entry -> entry.getKey(), entry.getValue())); 

Không phải là điều đẹp nhất, tuy nhiên, nhưng vẫn còn một giải pháp không đột biến.

+0

có cách nào tốt hơn trong Java7 không? –

1

Đối với Java 7, bạn không thể làm gì được nữa, bạn đã thực hiện nó theo cách tốt nhất có thể.

Tôi đang thêm câu trả lời này làm tham chiếu để cho thấy rằng đối với trường hợp như vậy bằng cách sử dụng Biểu thức Lambda trong Java 8 sẽ thậm chí tệ nhất. Xem ví dụ sau:

public static void main(String[] args) { 
    Map<String, String> map1 = new HashMap<>(); 
    final Map<String, String> map2 = new HashMap<>(); 

    for (int i=0; i<100000; i++){ 
     map1.put("k"+i, "v"+i); 
     map2.put("v"+i, "val"+i); 
    } 

    long time; 
    long prev_time = System.currentTimeMillis(); 
    for (Map.Entry<String, String> entry : map1.entrySet()) { 
     map1.put(entry.getKey(), map2.get(entry.getValue())); 
    } 
    time = System.currentTimeMillis() - prev_time; 
    System.out.println("Time after for loop " + time); 


    map1 = new HashMap<>(); 
    for (int i=0; i<100000; i++){ 
     map1.put("k"+i, "v"+i); 
    } 

    prev_time = System.currentTimeMillis(); 
    map1.replaceAll((k, v) -> map2.get(v)); 
    time = System.currentTimeMillis() - prev_time; 
    System.out.println("Time after for loop " + time); 
} 

Kết quả cho điều này sẽ là:

Time after for loop 40 
Time after for loop 100 

Vòng lặp thứ hai là biến nhưng luôn luôn lớn hơn cái đầu tiên.

Tôi không phải là Lambda chuyên gia nhưng tôi đoán rằng có nhiều để được xử lý với nó hơn là một đồng bằng "foreach" của kịch bản đầu tiên

Chạy test này hơn và hơn bạn sẽ nhận được cho lambda hầu như luôn luôn gấp đôi thời gian của trường hợp "foreach" đầu tiên.

Các vấn đề liên quan