2014-07-21 20 views
9

Phiên bản mới nhất của Bản đồ băm đồng thời của jdk 8 có hai Phương thức mới.ConcurrentHashMap JDK 8 khi sử dụng computeIfPresent

computeIfAbsent

computeIfPresent

putIfAbsent - Old phương pháp

Tôi hiểu các trường hợp sử dụng putIfAbsentcomputeIfAbsent. Nhưng tôi không chắc chắn về các tình huống khi tôi sẽ sử dụng computeIfPresent. Ngoài ra tại sao tôi cần putIfAbsent nếu tôi có computeIfPresent ngay bây giờ. putIfAbsent tạo ít nhất một phiên bản giá trị bổ sung.

Lý do chỉ có khả năng tương thích ngược?

Trả lời

24

Như đã đề cập trong câu trả lời khác: Phương pháp sẽ luôn được giữ để tương thích ngược, ngay cả khi có phương pháp mới, mạnh mẽ hơn được giới thiệu.

Liên quan đến trường hợp sử dụng cho computeIfPresent: Có thể khó tìm được một ví dụ đủ nhỏ để không bị giả tạo và vẫn thuyết phục. Nói chung, ý định của phương pháp này là để cập nhật giá trị hiện tại dưới mọi hình thức.

Một ví dụ có thể là (giới hạn) số từ: Đối với một tập hợp các từ nhất định, một cửa hàng có số lượng ban đầu là 0 trong bản đồ. Sau đó, một chuỗi các từ được xử lý: Bất cứ khi nào người ta tìm thấy một từ từ tập đầu tiên, số lượng của nó được tăng 1:

import java.util.LinkedHashMap; 
import java.util.Map; 

public class ComputeIfPresentExample 
{ 
    public static void main(String[] args) 
    { 
     Map<String, Integer> wordCounts = new LinkedHashMap<String, Integer>(); 

     String s = 
      "Lorem ipsum dolor sit amet consetetur iam nonumy sadipscing " + 
      "elitr, sed diam nonumy eirmod tempor invidunt ut erat sed " + 
      "labore et dolore magna dolor sit amet aliquyam erat sed diam"; 

     wordCounts.put("sed", 0); 
     wordCounts.put("erat", 0); 

     for (String t : s.split(" ")) 
     { 
      wordCounts.computeIfPresent(t, (k,v) -> v+1); 
     } 
     System.out.println(wordCounts); 
    } 
} 

(Tất nhiên, mọi thứ như thế này có thể được giải quyết khác nhau, nhưng đây là một thay công việc thường xuyên trong một hoặc hình thức khác, và phương pháp mới cho phép một giải pháp khá súc tích và thanh lịch)

0

JDK hầu như không bao giờ phá vỡ tính tương thích ngược. Bởi vì sau đó bạn không thể dễ dàng chuyển hoặc chạy phần mềm từ một phiên bản cũ hơn với phiên bản mới nhất.

Bạn có thể chạy phần mềm được biên dịch với phiên bản cũ hơn của thư viện với bất kỳ phiên bản nào (nghĩa là người dùng đã cài đặt JRE) vẫn có các chức năng đó.

+0

@thriller ohh tôi biết nó có được khả năng tương thích ngược. câu hỏi của tôi là lý do duy nhất? và cũng có thể sử dụng computeIfPresent. – veritas

0

Tôi đã sử dụng computeIfPresent như một cách an toàn để tìm giá trị chữ thường từ bản đồ chuỗi.

String s = fields.computeIfPresent("foo", (k,v) -> v.toLowerCase()) 

Trước computeIfPresent đã có sẵn tôi sẽ phải làm điều này:

String s = map.get("foo"); 
if (s != null) { 
    s = s.toLowerCase(); 
} 

Hoặc này:

String s = map.containsKey("foo") ? map.get("foo").toLowerCase() : null; 
0

Một trường hợp sử dụng phổ biến là maps với collections, như

Map<String, Collection<String>> strings = new HashMap<>(); 

computeIfAbsentcomputeIfPresent là các thao tác rất tiện lợi để thêm và xóa các phần tử vào/ra khỏi bộ sưu tập. Dưới đây là một ví dụ nhóm các chuỗi bằng char đầu tiên của chúng. Lưu ý rằng cả các phím và các bộ sưu tập được tạo ra khi cần thiết và làm sạch nó lên khi bộ sưu tập trở nên trống rỗng:

void addString(String a) { 
    String index = a.substring(0, 1); 
    strings.computeIfAbsent(index, ign -> new HashSet<>()).add(a); 
} 

void removeString(String a) { 
    String index = a.substring(0, 1); 
    strings.computeIfPresent(index, (k, c) -> { 
     c.remove(a); 
     return c.isEmpty() ? null : c; 
    }); 
} 

Đây là cực kỳ mạnh mẽ trong môi trường đa luồng như ConcurrentMaps thực hiện các hoạt động nguyên tử.

Ví dụ:

      // {} 
addString("a1");   // {a=[a1]}  <-- collection dynamically created 
addString("a2");   // {a=[a1, a2]} 
removeString("a1");  // {a=[a2]} 
removeString("a2");  // {}   <-- both key and collection removed 

Một số thêm đường:

void addString(String a) { 
    String index = a.substring(0, 1); 
    strings.computeIfAbsent(index, ign -> new HashSet<>()).add(a); 
} 

void removeString(String a) { 
    String index = a.substring(0, 1); 
    strings.computeIfPresent(index, (i, c) -> c.remove(a) && c.isEmpty() ? null : c); 
} 
Các vấn đề liên quan