2015-05-13 20 views
11

Trong Java, bạn có thể tạo mới HashMap để tổ chức một số cụ thể các mặt hàng như sau:khác biệt giữa new HashMap (int) và ổi Maps.newHashMapWithExpectedSize (int)

Map m = new HashMap(100); 

Ổi cung cấp một phương pháp Maps.newHashMapWithExpectedSize(int), mà tôi mong đợi chỉ cần gọi HashMap(int). Nhưng nó không làm điều này, thay vào đó nó tính toán năng lực của chính nó và sử dụng nó.

Tại sao newHashMapWithExpectedSize tự làm điều gì đó và tại sao tôi muốn sử dụng nó qua gọi trực tiếp new HashMap(int)?

+0

Câu trả lời của tôi bao gồm vấn đề này, nhưng vấn đề cơ bản ở đây là API JDK không tốt vì nó không kích thước 'HashMap'" để giữ một số mục cụ thể "như bạn mong đợi. Thay vào đó, kích thước của nó sẽ giữ 75% số bạn chỉ định. – ColinD

Trả lời

6

Bạn đã đọc phương thức Javadoc của phương pháp chưa?

Ví dụ, với công suất ban đầu "đủ cao" cần giữ expectedSize yếu tố không tăng trưởng.

Lưu ý rằng "kích thước ban đầu" tham số new HashMap(int) constructor của quy định cụ thể kích thước ban đầu của bảng băm rằng mục được lưu trữ trong, mà về cơ bản là một chi tiết thực hiện mà bạn không cần phải quan tâm. Bảng băm sẽ thay đổi kích thước khi nó vượt quá yếu tố tải (mặc định là 0,75), có nghĩa là nếu bạn chỉ định dung lượng ban đầu là 16 và sau đó thêm 16 mục vào bản đồ, bảng băm sẽ gần như chắc chắn được thay đổi kích thước.

Với phương pháp của ổi, nếu bạn chỉ định kích thước mong đợi trong số 16 và sau đó thêm 16 mục nhập, bảng băm phải không đổi kích thước.

+0

Không, bạn là ví dụ sẽ không làm điều này. Thư viện chuẩn sẽ làm tròn kích thước lên đến 16 (lũy thừa tiếp theo là 2) và điền nó với 10 mục sẽ không vượt quá ngưỡng để mở rộng kích thước. Tuy nhiên nếu bạn có một kích thước dự kiến ​​là 13 và điền nó với 13 nó sẽ. –

+0

Cảm ơn, cố định ví dụ cụ thể để sử dụng 16. Đối với các kích thước tùy ý, nó vẫn đúng là bảng có thể thay đổi kích thước nếu bạn chỉ định dung lượng ban đầu bằng số lượng mục bạn muốn thêm. – ColinD

0

Chỉ cần nhân kích thước được truyền qua 2 (theo cách an toàn) và gọi hàm tạo băm thông thường. Điều này làm cho nó thưa thớt hơn nên có ít va chạm hơn trong khi băm.

javadoc về tính toán dung lượng đề cập đến tính toán giá trị cho dung lượng sao cho băm bản đồ nằm trong khoảng từ 25% đến 50% đầy đủ, cách xa ngưỡng sẽ kích hoạt thay đổi kích thước.

Thư viện chuẩn làm tròn kích thước dự kiến ​​lên đến sức mạnh gần nhất của 2 và phân bổ kích thước đó và sau đó đặt ngưỡng để thay đổi kích thước thành 75%. Nếu chúng tôi yêu cầu kích thước ngẫu nhiên, thư viện chuẩn sẽ thay đổi kích thước trong 50% các trường hợp.

Nếu tránh ngưỡng sẽ là xem xét duy nhất, nhân với 1,34 sẽ đủ để có đủ không gian để tránh thay đổi kích thước khi lấp đầy nó với kích thước mong đợi của các phần tử.

Dường như tốc độ điển hình so với giao diện không gian và các kỹ sư của Google có tốc độ nhanh hơn và các kỹ sư Sun/Oracle có nhiều không gian hơn.

+1

Không. Nếu bạn gọi 'HashMap mới (n)' và sau đó đặt n mục vào, bảng băm sẽ được thay đổi kích thước bởi vì nó không đủ lớn theo định nghĩa của JDK; Ổi chỉ bù đắp cho điều đó. –

+0

Vâng, như Louis đã nói, bảng băm sẽ kết thúc xấp xỉ cùng một kích thước bất kể bạn sử dụng phương pháp nào để xây dựng 'Bản đồ', do đó không nên có bất kỳ không gian quan trọng nào khác nhau. Sự khác biệt duy nhất là có hay không bảng băm sẽ phải được thay đổi kích thước trước khi tất cả các mục bạn muốn thêm có thể được thêm vào. – ColinD

+0

vâng, bạn nói đúng. Nó phân bổ kích thước được làm tròn lên lũy thừa tiếp theo là 2 và sau đó thiết lập loadfactor bình thường là 75%, sẽ được kích hoạt khi điền nó với các mục kích thước (nếu kích thước đủ gần với số được làm tròn, hoặc khoảng 50% các trường hợp). Tôi đã bị lầm tưởng rằng thư viện chuẩn đã đền bù cho việc này. Tuy nhiên, số 2 là khá tùy ý, vì vậy tôi vẫn tin rằng sự thưa thớt đóng một vai trò có quá. –

1

Đối số hàm tạo HashMap là dung lượng của bản đồ, nghĩa là số lượng nhóm.

Vì vậy, nếu bạn vượt qua 10 làm đối số và lưu 8 khóa trong bản đồ, ngưỡng phục hồi (75% theo mặc định) sẽ được truy cập và bản đồ sẽ được phục hồi.

Mặt khác, đối số được truyền cho newHashMapWithExpectedSize() là kích thước dự kiến ​​của bản đồ.Vì vậy, nếu bạn vượt qua 10, Ổi sẽ tạo bản đồ có đủ nhóm để đảm bảo bản đồ không được phục hồi khi chèn 10 phần tử: ít nhất 14 nhóm.

+1

Một 'HashMap' sử dụng sức mạnh tiếp theo của hai là khả năng của nó. Vì vậy, nếu bạn đặt 'initialCapacity' thành 10, dung lượng thực sẽ là 16. Tính toán bằng 0.75 kết quả tổng cộng 12 mục nhập mà không thay đổi kích thước. – Bubletan

+1

@Bubletan: Điều này đúng, nhưng A) đó là chi tiết triển khai hoàn toàn không được chỉ định bởi API và B) nó không thay đổi thực tế là đối với nhiều giá trị có thể có của 'initialCapacity', bảng sẽ phải được thay đổi kích thước và đã được phục hồi để thêm nhiều mục nhập đó. – ColinD

+0

@ColinD đồng ý, không có cách nào để biết khả năng ban đầu thực tế từ javadoc mà không đọc mã. Nó thực sự gây hiểu lầm ở một số nơi. –

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