2009-05-08 49 views

Trả lời

28

Các documentations nói:

Một sử dụng điển hình của lớp này là topo bảo quản đối tượng đồ thị biến đổi, chẳng hạn như serialization hoặc sâu sao chép. Để thực hiện việc chuyển đổi như vậy, chương trình phải duy trì "bảng nút" giữ theo dõi tất cả các tham chiếu đối tượng đã được xử lý. Bảng nút không được phân biệt các đối tượng riêng biệt ngay cả khi chúng xảy ra là bằng nhau. Một cách sử dụng điển hình của lớp này là duy trì các đối tượng proxy. Ví dụ: cơ sở gỡ lỗi có thể muốn duy trì đối tượng proxy cho từng đối tượng trong chương trình đang được gỡ lỗi.

+3

Tôi đến từ tài liệu, tìm kiếm lời giải thích về SO – Rockstar5645

32

Bất cứ khi nào bạn muốn khóa không được so sánh bằng equals nhưng bằng == bạn sẽ sử dụng IdentityHashMap. Điều này có thể rất hữu ích nếu bạn đang thực hiện rất nhiều xử lý tham chiếu nhưng nó chỉ giới hạn trong các trường hợp rất đặc biệt.

+1

Hành vi của so sánh ison là vé ở đây. Tôi đã sử dụng HashMaps "Identity" để lưu trữ siêu dữ liệu cần được liên kết với một đối tượng cụ thể. Giá trị bình đẳng của các đối tượng có thể giống nhau. Tuy nhiên, cẩn thận phải được thực hiện để đảm bảo bản gốc được bảo quản miễn là tra cứu [trực tiếp] là bắt buộc - và phải cẩn thận để tránh bộ nhớ "rò rỉ". –

+2

Ngoài ra, vì bất biến danh tính (o == o => true, đối với bất kỳ o nào), IdentityHashMap có thể được sử dụng * ngay cả khi các đối tượng chính bị biến đổi *. Nhưng bạn không sử dụng các khóa có thể thay đổi được ... là bạn? (Có lẽ tôi nên ngồi trong một góc và khóc.) –

12

Đây là một kinh nghiệm thực tiễn từ tôi:

IdentityHashMap để lại một bộ nhớ nhỏ hơn nhiều so với HashMap cho cardinalities lớn.

19

Một trường hợp bạn có thể sử dụng IdentityHashMap là nếu khóa của bạn là đối tượng Lớp. Tốc độ này nhanh hơn 33% so với HashMap! Nó có thể sử dụng ít bộ nhớ hơn.

+1

Bạn có bất kỳ nguồn/điểm chuẩn nào để trả lại khiếu nại đó không? – kgdinesh

+1

@DineshBabu Không có gì thực sự kết luận. Có [this] (http://www.java-gaming.org/index.php?topic=21395.0) nhưng tất nhiên microbenchmarks thay đổi theo JVM, kích thước bản đồ, chất lượng mã băm, bằng thực hiện, giai đoạn của mặt trăng, v.v. IdentityHashMap tránh đối tượng Entry (có tác động GC) và sử dụng == để so sánh, vì vậy dự kiến ​​sẽ thực hiện tốt hơn một chút. Bạn có thể thích [bản đồ cuckoo] của tôi (https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils/ObjectMap.java), đã được sử dụng rộng rãi trong libgdx và Kryo. Có một số bản đồ khác trong cùng một gói, bao gồm cả IdentityMap. – NateS

16

HashMap tạo đối tượng mục nhập mỗi lần bạn thêm đối tượng, điều này có thể gây căng thẳng cho GC khi bạn có nhiều đối tượng. Trong HashMap với 1.000 đối tượng hoặc nhiều hơn, bạn sẽ sử dụng một phần tốt của CPU của bạn chỉ có các mục làm sạch GC (trong các tình huống như pathfinding hoặc các bộ sưu tập một shot khác được tạo và sau đó được làm sạch). IdentityHashMap không có vấn đề này, do đó sẽ kết thúc nhanh hơn đáng kể.

Xem một chuẩn mực ở đây: http://www.javagaming.org/index.php/topic,21395.0/topicseen.html

+0

Hehe, tôi là cùng một Nate. – NateS

+0

:-) Aha! Đi JGO. – Eli

3

Một trường hợp quan trọng là nơi bạn đang đối phó với các loại tài liệu tham khảo (như trái ngược với các giá trị) và bạn thực sự muốn kết quả chính xác. Các đối tượng độc hại có thể đã ghi đè các phương thức hashCodeequals nhận được tất cả các loại tinh nghịch. Thật không may, nó không được sử dụng thường xuyên như nó phải được. Nếu loại giao diện bạn đang xử lý không ghi đè hashCodeequals, bạn thường nên truy cập IdentityHashMap.

12

Bạn cũng có thể sử dụng IdentityHashMap như một bản đồ mục đích chungnếu bạn có thể đảm bảo các đối tượng bạn sử dụng như phím sẽ bằng khi và chỉ khi tài liệu tham khảo của họ đều bình đẳng.

Để đạt được điều gì? Rõ ràng nó sẽ là nhanh hơn và sẽ sử dụng ít bộ nhớ hơn so với việc sử dụng các triển khai như HashMap hoặc TreeMap.


Trên thực tế, có khá nhiều trường hợp khi điều này đứng. Ví dụ:

  • Enum s. Mặc dù cho enums thậm chí còn có một lựa chọn tốt hơn: EnumMap
  • Class đối tượng. Chúng cũng có thể so sánh bằng tham chiếu.
  • Thực tập String s. Hoặc bằng cách chỉ định chúng là literals hoặc gọi String.intern() trên chúng.
  • Phiên bản được lưu trong bộ nhớ cache. Một số lớp cung cấp bộ nhớ đệm cho các thể hiện của chúng. Ví dụ trích dẫn từ javadoc của Integer.valueOf(int):

    Phương pháp này sẽ luôn luôn giá trị bộ nhớ cache trong khoảng -128 đến 127, bao gồm ...

  • Một số thư viện/framework sẽ quản lý chính xác một thể hiện của loại ceratin, cho Ví dụ đậu mùa xuân.
  • Loại Singleton. Nếu bạn sử dụng các loại được xây dựng với mẫu Singleton, bạn cũng có thể chắc chắn rằng (ít nhất) một cá thể tồn tại từ chúng và do đó kiểm tra bình đẳng tham chiếu sẽ đủ điều kiện cho kiểm tra bình đẳng.
  • Bất kỳ loại nào khác mà bạn sử dụng cẩn thận chỉ sử dụng cùng một tham chiếu để truy cập các giá trị được sử dụng để đưa các giá trị vào bản đồ.


Để chứng minh điểm cuối cùng:

Map<Object, String> m = new IdentityHashMap<>(); 

// Any keys, we keep their references 
Object[] keys = { "strkey", new Object(), new Integer(1234567) }; 

for (int i = 0; i < keys.length; i++) 
    m.put(keys[i], "Key #" + i); 

// We query values from map by the same references: 
for (Object key : keys) 
    System.out.println(key + ": " + m.get(key)); 

Output sẽ được, như mong đợi (vì chúng tôi sử dụng các tài liệu tham khảo cùng Object để truy vấn giá trị từ bản đồ):

strkey: Key #0 
[email protected]: Key #1 
1234567: Key #2 
Các vấn đề liên quan