2012-12-28 14 views
6

Tôi cần kiểm tra xem bản đồ có chứa bất kỳ khóa nào trong danh sách hay không và nếu bản đồ đó trả về giá trị khớp đầu tiên. Cách tiếp cận ngây thơ đến với tâm trí là làm điều đó trong hai vòng lồng nhau:Cách hiệu quả để tìm xem bản đồ có chứa bất kỳ khóa nào từ danh sách/có thể lặp lại

Map<String, String> fields = new HashMap<String, String>(); 
fields.put("a", "value a"); 
fields.put("z", "value z"); 
String[] candidates = "a|b|c|d".split("|"); 
for (String key : fields.keySet()){ 
    for (String candidate : candidates) { 
     if (key.equals(candidate)){ 
      return fields.get(key); 
     } 
    } 
} 

Có cách nào đẹp hơn và hiệu quả hơn, có thể dựa vào thư viện chuẩn Java?

Trả lời

19

Chắc chắn cái gì đó như:

for (String candidate : candidates) { 
    String result = fields.get(key); 
    if (result != null) { 
     return result; 
    } 
} 

Trên đây chỉ thực hiện một tra cứu bản đồ cho mỗi khoá ứng cử viên. Nó tránh thử nghiệm riêng biệt cho sự hiện diện cộng với khai thác, vì việc trích xuất một khóa không tồn tại sẽ đơn giản cung cấp cho bạn một giá trị rỗng. Lưu ý (cảm ơn Slanec) rằng giá trị null cho khóa hợp lệ không thể phân biệt được từ khóa không tồn tại cho giải pháp này.

Tôi không hiểu tại sao bạn thực hiện chuyển đổi trường hợp, btw.

+8

Đây là hiệu quả như nó có thể nhận được, nhưng nó có thể trở nên phức tạp nếu 'null' là giá trị được phép trong' Bản đồ'. –

+3

Thú vị ... Tôi có hiểu chính xác rằng ý tưởng là chỉ sử dụng bản đồ.get() 'một lần thay vì' map.contains() + map.get() 'vì điều đó sẽ tránh được lần tra cứu thứ hai? Đó là gọn gàng! – ccpizza

+3

@NimChimpsky retainTất cả là tiêu cực. –

20
for(String candidate : candidates) { 
if(fields.containsKey(candidate)) { 
    return fields.get(candidate) 
} 
} 

cách tốt nhất nếu giá trị null có thể có trong bản đồ và nếu chỉ có khóa được phát hiện đầu tiên là bắt buộc.

7

tôi mất:

Map<String, String> fields = new HashMap<String, String>(); 
fields.put("a", "value a"); 
fields.put("z", "value z"); 
String[] candidates = "a|b|c|d".split("|"); 
for (String candidate : candidates) { 
    if (fields.containsKey(candidate)) { 
     return fields.get(candidate); 
    } 
} 
1
Map<String, String> fields = new HashMap<String, String>(); 
fields.put("a", "value a"); 
fields.put("z", "value z"); 
String[] candidates = "a|b|c|d".split("|"); 
List<String> canList = Arrays.asList(candidates); 
for (String key : fields.keySet()){ 

if (canList .contains(key)) { 
return fields.get(key); 
} 

} 
+1

** Lưu ý **: canList.contains là tuyến tính đúng lúc. – Srinivas

2

Hãy thử như

List list= Arrays.asList(1, 2, 3); 
    HashMap map = new HashMap(); 
    map.put(1, 1); 
    map.put(3, 3); 
    Set set = new HashSet(map.keySet()); 
    set.retainAll(list); 
    System.out.println(set); 
    Object e = set.isEmpty() ? null : set.iterator().next(); 
    System.out.println(e); 

đầu ra

[1, 3] 
1 
5

Hãy thử

Set<String> keySet = new HashSet<String>(fields.keySet());  
keySet.retainAll(list); 

nên keySet là phải có tất cả các phím từ HashMap được đề cập trong danh sách

+2

Đây là, tôi tin rằng, cách ngắn nhất. Tuy nhiên, nó có thể không phải là nhanh nhất kể từ khi vòng lặp kết thúc tại kết quả tìm thấy đầu tiên, nhưng điều này tiếp tục công việc của nó cho đến cuối. –

+3

@Slanec, vâng nó phụ thuộc vào việc OP muốn nhận được tất cả các phím hoặc chỉ là một trong những đầu tiên. –

1

Bạn có thể sử dụng một vòng lặp đơn nếu bạn giả định khóa của bản đồ đã ở trong trường hợp thấp hơn, giống như cách bạn giả định giá trị tra cứu trong trường hợp thấp hơn.

4

Trong Java 8 bạn có thể sử dụng này:

return candidates.stream() 
      .filter(fields::containsKey) 
      .findFirst() 
      .map(fields::get) 
      .orElse(null); 
5

Trong Java 8 bạn có thể có điều này:

boolean exists = Arrays.stream(candidates).anyMatch(fields::containsKey); 

Nếu bạn chỉ muốn biết nếu có của các ứng cử viên là chìa khóa để bản đồ.

Nếu bạn muốn biết người đầu tiên hoặc bất kỳ mà bạn có thể sử dụng:

Arrays.stream(candidates).filter(fields::containsKey).findAny(); 

hoặc

Arrays.stream(candidates).filter(fields::containsKey).findFirst(); 

Theo @ Klapsa2503 câu trả lời ở trên

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