2016-11-08 13 views
5

Tôi có một phương pháp với chữ ký sau đây:Tại sao Bản đồ không <String, Đặt <String>> khớp với Bản đồ <T, Set<?>>?

public <T> int numberOfValues(Map<T, Set<?>> map) 

Tuy nhiên tôi không thể gọi nó đi qua trong một Map<String, Set<String>>. Ví dụ, sau đây không biên dịch:

Map<String, Set<String>> map = new HashMap<>(); 
numberOfValues(map); 

Các thông báo lỗi được rằng:

numberOfValues (java.util.Map<java.lang.String,java.util.Set<?>>) in class cannot be applied to (java.util.Map<java.lang.String,java.util.Set<java.lang.String>>) 

Tuy nhiên, nếu tôi thay đổi như sau tất cả là tốt:

public <T, V> int numberOfValues(Map<T, Set<V>> map) 

Tuy nhiên Tôi hoàn toàn không quan tâm đến V, vì tôi chỉ muốn biết kích thước của từng bộ.

Vì đầy đủ, đây là toàn bộ phương pháp:

public <T, V> int numberOfValues(Map<T, Set<V>> map) { 
    int n = 0; 
    for (T key : map.keySet()) { 
     n += map.get(key).size(); 
    } 
    return n; 
} 

nào Tôi biết nó cũng có thể được thực hiện như thế này, nhưng không phải là quan điểm của câu hỏi :)

public <T> int numberOfValues(Map<?, Set<T>> map) { 
    int n = 0; 
    for (Set<T> value : map.values()) { 
     n += value.size(); 
    } 
    return n; 
} 

cập nhật: chưa một cách khác để đạt được cùng một

public <T> int numberOfValues(Map<?, Set<T>> map) { 
    int n = 0; 
    for (Object key : map.keySet()) { 
     n += map.get(key).size(); 
    } 

    return n; 
} 

cập nhật cuối cùng: Nhờ câu trả lời Jorn, đây là việc thực hiện cuối cùng ...

public int numberOfValues(Map<?, ? extends Set<?>> map) { 
    int n = 0; 
    for (Set<?> value : map.values()) { 
     n += value.size(); 
    } 
    return n; 
} 
+3

Bạn đã không được hiển thị như thế nào bạn đang cố gắng gọi phương thức, mà làm cho nó khó khăn để giúp bạn. Vui lòng cung cấp [mcve]. –

+0

Đã sửa, tôi đã thêm đoạn mã về cách thức phương thức được gọi với một bản đồ trống. – Alf

+0

Và không thể 'map.get (key)' return 'null'? –

Trả lời

10

Bạn đang thiếu thực tế là Set<?> cũng được sử dụng như một tham số chung. Và generics là bất biến. tức là khi tham số là Map<String, Set<?>>, đối số đã truyền phải chính xác là Map<String, Set<?> (hoặc loại phụ của). Trong khi với Set<V>, đối số kiểu được suy ra.

Bạn có thể giải quyết điều này bằng cách sử dụng một ký tự đại diện bị chặn:

public <T> int numberOfValues(Map<T, ? extends Set<?>> map) { 
    ... 
} 
+0

Cảm ơn, điều đó có ý nghĩa. Tôi đã chỉnh sửa câu hỏi và thêm một triển khai không có loại nào cả. – Alf

0

Gợi ý:

Trong phương pháp numberOfValues của bạn, nó là hoàn toàn hợp pháp để viết một cái gì đó giống như

Set<Object> set = new HashSet<>(); 
set.add(1); 
set.add("Powned"); 
map.put(null, set); 

Bạn có thể thay thế null với khóa phù hợp đã có trên bản đồ để tạo bản đồ hợp lệ, phá vỡ hoàn toàn loại an toàn trong mã xung quanh.

Hoặc suy ra hoặc xác định rõ kiểu dữ liệu của bộ này, hoặc thêm một ký tự đại diện ràng buộc ngăn ngừa đột biến truy cập bản đồ (như ? extends Set<?>)

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