2010-01-15 25 views
6

UnmodifiableCollection.get được khởi tạo tĩnh có được bảo đảm không?Là unmodifiableCollection.get được khởi tạo tĩnh có được bảo đảm không?

Mục đích:

static final Map FOO = Collections.unmodifiableMap (new HashMap());

Nhiều chủ đề có thể sử dụng phương thức nhận và không gặp sự cố không? Ngay cả thông qua các mục trong FOO không thể được thêm vào/gỡ bỏ, điều gì ngăn cản phương thức get điều khiển trạng thái bên trong của FOO cho mục đích lưu trữ, vv. Nếu trạng thái bên trong được sửa đổi theo bất kỳ cách nào thì không thể sử dụng đồng thời FOO. Nếu đây là trường hợp, đâu là những bộ sưu tập bất biến thực sự trong java?

+1

Thực ra là một câu hỏi hay. Hãy suy nghĩ 'WeakHashMap' - có thể thay đổi mà không thay đổi. 'LinkedHashMap' trong chế độ truy cập là giống nhau. –

+0

(Bạn có thể muốn sao chép tiêu đề câu hỏi của mình vào câu hỏi - biểu ngữ bị mù.) –

+0

Tác giả có một câu hỏi hay. Giả sử tôi viết triển khai bản đồ của riêng tôi. Hãy giả sử rằng khi mỗi lần tra cứu, nó sẽ tổ chức lại cấu trúc bên trong của nó để hầu hết các mục được tìm kiếm nhanh hơn trong thời gian tới. Kết thúc tốt đẹp của người dùng đã nói bản đồ với bộ sưu tập không thể sửa đổi và giả định đó là chủ đề an toàn. Sau đó, 2 chủ đề truy cập các giá trị khác nhau cùng một lúc và vít tối ưu hóa nội bộ lên trạng thái bên trong của bản đồ. – z5h

Trả lời

-1

Tôi sẽ đề xuất cho bất kỳ hoạt động luồng nào để sử dụng ConcurrentHashMap hoặc HashTable, cả hai đều là an toàn chỉ.

+0

Ai đó đang trên bầu cử xuống spree, lol. –

+1

Vâng, sử dụng các hoạt động đồng thời cho dữ liệu bất biến có lẽ là một ý tưởng tồi. –

0

Không có bản đồ bất biến thực sự trong Java SDK. Tất cả các bản đồ được đề xuất bởi Chris chỉ là chủ đề an toàn. Bản đồ unmodifiable không phải là bất biến, hoặc kể từ khi bản đồ cơ bản thay đổi sẽ có ConcurrentModificationException là tốt.

Nếu bạn muốn bản đồ thực sự bất biến, hãy sử dụng ImmutableMap từ Google Collections/Guava.

-1

Cho dù bộ thu thập trên bản đồ trả về có xảy ra với một số trạng thái nội bộ không quan trọng, miễn là đối tượng tôn trọng hợp đồng của nó (đó là bản đồ không thể sửa đổi được). Vì vậy, câu hỏi của bạn là "sủa cây sai".

Bạn có quyền thận trọng với UnmodifiableMap, trong trường hợp bạn không có quyền sở hữu và kiểm soát bản đồ mà nó kết thúc tốt đẹp. Ví dụ:

Map<String,String> wrapped = new HashMap<String,String>(); 
wrapped.add("pig","oink"); 
Map<String,String> wrapper = Collections.unmodifiableMap(wrapped); 
System.out.println(wrapper.size()); 
wrapper.put("cow", "moo"); // throws exception 
wrapped.put("cow", "moo"); 
System.out.println(wrapper.size()); // d'oh! 
+0

"không quan trọng" - không đúng! Nó rất quan trọng nếu lớp không an toàn thread và hai luồng đang bước qua nhau! –

+0

Đọc lại, thưa ông. "Miễn là nó tôn trọng hợp đồng của nó." –

0

Thực ra là một câu hỏi hay. Hãy suy nghĩ WeakHashMap - điều đó có thể thay đổi mà không cần phải có hoạt động đột biến được gọi trên đó. LinkedHashMap trong chế độ đặt hàng truy cập giống nhau.

Các tài liệu API cho HashMap nhà nước:

Lưu ý rằng việc thực hiện điều này không phải là đồng bộ. Nếu có nhiều chủ đề truy cập một bản đồ băm đồng thời và tại ít nhất một trong các chủ đề sửa đổi cấu trúc bản đồ , thì phải đồng bộ hóa bên ngoài. (A sửa đổi cấu trúc là bất kỳ hoạt động mà thêm hoặc xóa một hoặc nhiều ánh xạ; chỉ đơn thuần là thay đổi giá trị liên quan đến với một chìa khóa mà một thể hiện đã chứa không phải là một cấu trúc sửa đổi.)

Có lẽ đó nên nếu và chỉ khi. Điều đó có nghĩa rằng get không cần phải được đồng bộ hóa nếu HashMap là 'không thay đổi có hiệu quả'.

+0

Mr/Ms Downvoter: Bất cứ điều gì sai trái với câu trả lời của tôi, hay chỉ trả thù? –

4

Với ví dụ cụ thể:

static final Map FOO = Collections.unmodifiableMap(new HashMap()); 

Sau đó FOO sẽ không thay đổi. Nó cũng sẽ không bao giờ có bất kỳ yếu tố nào.Với trường hợp chung chung hơn:

static final Map BAR = Collections.unmodifiableMap(getMap()); 

Sau đó, điều này là không thay đổi hoàn toàn phụ thuộc vào việc người khác có thể vào Bản đồ cơ bản hay không và loại bản đồ nào. Ví dụ, nếu nó là một LinkedHashMap thì danh sách liên kết bên dưới có thể được sửa đổi theo thứ tự truy cập, và có thể thay đổi bằng cách gọi get(). Cách an toàn nhất (sử dụng các lớp học không đồng thời) để làm điều này sẽ là:

static final Map BAR = Collections.unmodifiableMap(new HashMap(getMap())); 

các javadocs for HashMap ngụ ý rằng chừng nào bạn thực hiện không thay đổi cấu trúc bản đồ, sau đó nó là an toàn để sử dụng nó đồng thời, vì vậy đây nên an toàn cho bất kỳ người truy cập nào mà bạn có thể sử dụng, đó là nhận các tập hợp khác nhau và lặp lại chúng và nhận() sau đó sẽ an toàn.

Nếu bạn có thể sử dụng các lớp học đồng thời, sau đó bạn cũng có thể làm:

static final Map BAR = Collections.unmodifiableMap(new ConcurrentHashMap(getMap()); 

Đây sẽ là một cách rõ ràng an toàn để sử dụng từ nhiều chủ đề, từ ConcurrentHashMap là rõ ràng multi-thread an toàn truy cập. Trạng thái bên trong có thể có thể thay đổi, nhưng trạng thái hiển thị bên ngoài sẽ không được, và vì lớp được đảm bảo là luồng an toàn, chúng ta có thể xem xét nó một cách an toàn bên ngoài.

+0

Nếu tôi muốn lặp lại qua 'BAR' thì sao? –

+0

@Tom: Khi bạn đề cập đến trong câu trả lời của bạn, và bây giờ tôi đề cập đến trong của tôi ;-), lặp lại trên bản đồ nên được an toàn như sử dụng nhận được. –

+0

Nhưng bạn đang nói về 'ConcurrentHashMap' và' Map 'của việc triển khai không xác định. –

2

Rủi ro có vẻ như tôi đang ở trên quảng cáo, hãy sử dụng số Google Immutable Collections và được thực hiện với nó.

+0

Tại sao bạn lại giới thiệu một sự phụ thuộc như thế mà không có lý do? –

+0

Tại sao phải vượt qua rào cản để đảm bảo tính bất biến khi một số người khác đã có? – Carl

+3

Tom, một số người chỉ có một sở thích về phong cách cho "Bản đồ cuối cùng tĩnh công cộng MAP = Bản đồ bất biến.của (foo1, bar1, foo2, bar2), 'trên' sơ đồ tĩnh công cộng cuối cùng MAP = initMap(); Bản đồ tĩnh riêng initMap() {Bản đồ bản đồ = new HashMap (); map.put (foo1, bar1); map.put (foo2, bar2); return Collections.unmodifiableMap (bản đồ); } '. –

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