Tôi nên sử dụng Bộ sưu tập Java nào?


127

Trong câu hỏi này Làm thế nào tôi có thể chọn hiệu quả bộ chứa Thư viện chuẩn trong C ++ 11? là một biểu đồ dòng tiện dụng để sử dụng khi chọn các bộ sưu tập C ++.

Tôi nghĩ rằng đây là một tài nguyên hữu ích cho những người không chắc chắn họ nên sử dụng bộ sưu tập nào nên tôi đã cố gắng tìm một biểu đồ luồng tương tự cho Java và không thể làm như vậy.

Những tài nguyên và "bảng cheat" nào có sẵn để giúp mọi người chọn Bộ sưu tập phù hợp để sử dụng khi lập trình bằng Java? Làm thế nào để mọi người biết những gì triển khai Danh sách, Bộ và Bản đồ họ nên sử dụng?


Cuốn sách Java Generics and Collection (Naftalin & Wadler) có một chương về điều này.
Barshe Roussy

Câu trả lời:


292

Vì tôi không thể tìm thấy một sơ đồ tương tự, tôi quyết định tự làm một cái.

Biểu đồ luồng này không thử và bao gồm những thứ như truy cập được đồng bộ hóa, an toàn luồng, v.v. hoặc các bộ sưu tập kế thừa, nhưng nó bao gồm 3 Bộ tiêu chuẩn , 3 Bản đồ tiêu chuẩn và 2 Danh sách tiêu chuẩn .

nhập mô tả hình ảnh ở đây

Hình ảnh này được tạo cho câu trả lời này và được cấp phép theo Giấy phép Quốc tế Creative Commons Attribution 4.0. Sự quy kết đơn giản nhất là bằng cách liên kết với câu hỏi này hoặc câu trả lời này.

Các nguồn lực khác

Có lẽ tài liệu tham khảo khác hữu ích nhất là trang sau từ tài liệu tiên tri mô tả mỗi Bộ sưu tập .

Hashset vs Treeset

Có một cuộc thảo luận chi tiết về thời điểm sử dụng HashSethoặc TreeSetở đây: Hashset vs Plantset

ArrayList vs LinkedList

Thảo luận chi tiết: Khi nào nên sử dụng LinkedList trên ArrayList?


Đẹp! Nhưng tôi phải đồng ý với bạn LinkedListvs ArrayListquyết định. Đầu tiên, nếu danh sách có kích thước đáng kể, LinkedListtốt hơn là. LinkedListcó chi phí cho mỗi phần tử, do đó, nó kém hơn về mặt tiêu thụ bộ nhớ so với một ArrayList. Ngoài ra, nếu hầu hết các truy cập nằm ở cuối danh sách, ArrayListthì tốt hơn là vì nó cung cấp truy cập phần tử ngẫu nhiên theo thời gian không đổi. Truy cập nphần tử thứ của a LinkedListlà một O(n)hoạt động. ... Trên thực tế, quyết định sử dụng danh sách được liên kết nên luôn luôn là "không".
Matt Ball

2
@MattBall Tôi đồng ý với bạn phần lớn. Tuy nhiên, Java LinkedListlà một danh sách liên kết kép, vì vậy truy cập lúc bắt đầu và lúc kết thúc đều nhanh. Bạn sẽ lưu ý rằng các nhánh trên cả ba câu hỏi phải trả lời có trước khi tôi khuyên bạn nên sử dụng LinkedList- vì vậy nói cách khác tôi đồng ý với bạn rằng trong hầu hết các trường hợp, câu trả lời là không. Những thứ như hàng đợi và dequeues nơi bạn liên tục thêm và xóa những thứ từ cuối khu vực danh sách trường hợp sử dụng tốt cho LinkedList.
Tim B

@MattBall Việc sử dụng bộ nhớ là một tình huống khó khăn hơn nhiều vì trong khi việc LinkedListsử dụng nhiều bộ nhớ hơn cho mỗi phần tử ... ArrayListkhông bao giờ giải phóng bộ nhớ. Điều đó có nghĩa là nếu bạn có một danh sách đôi khi phát triển đến kích thước khổng lồ nhưng thường nhỏ thì ArrayListsẽ cho hiệu năng bộ nhớ kém hơn. Chi phí bộ nhớ của Listchính nó thường (mặc dù không phải lúc nào) nhỏ so với các phần tử mà nó chứa.
Tim B

Map<K,V>không phải là một phần củajava.util.collection
Mehraj Malik

@MehrajMalik Hmm, việc dán nhãn không rõ ràng tôi đồng ý. Tôi có nghĩa là Bộ sưu tập bên trong java.util. tức là java.util. * chèn tên bộ sưu tập vào đây *
Tim B

66

Tóm tắt các bộ sưu tập chính không đồng thời, không đồng bộ

Collection: Giao diện đại diện cho "túi" vật phẩm không có thứ tự, được gọi là "phần tử". Phần tử "tiếp theo" không xác định (ngẫu nhiên).

  • Set: Một giao diện đại diện cho a Collectionkhông có bản sao.
    • HashSet: A được Sethỗ trợ bởi a Hashtable. Sử dụng bộ nhớ nhanh nhất và nhỏ nhất, khi đặt hàng là không quan trọng.
    • LinkedHashSet: A HashSetvới việc thêm danh sách được liên kết vào các phần tử liên kết theo thứ tự chèn . Phần tử "tiếp theo" là phần tử được chèn gần đây nhất.
    • TreeSet: A Settrong đó các phần tử được sắp xếp theo thứ tựComparator (thường là thứ tự tự nhiên ). Sử dụng bộ nhớ chậm nhất và lớn nhất, nhưng cần thiết cho việc đặt hàng dựa trên bộ so sánh.
    • EnumSet: Một Settùy chỉnh cực kỳ nhanh chóng và hiệu quả cho một loại enum.
  • List: Giao diện đại diện cho một Collectionphần tử được sắp xếp theo thứ tự và mỗi phần tử có một chỉ số số biểu thị vị trí của nó, trong đó zero là phần tử đầu tiên và (length - 1)là phần tử cuối cùng.
    • ArrayList: A được Listhỗ trợ bởi một mảng, trong đó mảng có độ dài (được gọi là "dung lượng") ít nhất bằng số lượng phần tử ("kích thước" của danh sách). Khi kích thước vượt quá dung lượng (khi (capacity + 1)-thphần tử được thêm vào), mảng được tạo lại với công suất mới (new length * 1.5)- giải trí này rất nhanh, vì nó sử dụng System.arrayCopy(). Xóa và chèn / thêm các phần tử yêu cầu tất cả các phần tử lân cận (bên phải) được chuyển vào hoặc ra khỏi không gian đó. Truy cập bất kỳ yếu tố nào là nhanh chóng, vì nó chỉ yêu cầu tính toán (element-zero-address + desired-index * element-size)để tìm vị trí của nó. Trong hầu hết các tình huống , một ArrayListđược ưa thích hơn a LinkedList.
    • LinkedList: A được Listhỗ trợ bởi một tập hợp các đối tượng, mỗi đối tượng được liên kết với các hàng xóm "trước" và "tiếp theo" của nó. A LinkedListcũng là một QueueDeque. Việc truy cập các phần tử được thực hiện bắt đầu từ phần tử đầu tiên hoặc phần tử cuối cùng và di chuyển ngang cho đến khi đạt được chỉ mục mong muốn. Chèn và xóa, một khi đạt được chỉ số mong muốn thông qua truyền tải là một vấn đề tầm thường khi chỉ ánh xạ lại các liên kết lân cận ngay lập tức để trỏ đến phần tử mới hoặc bỏ qua phần tử hiện đã bị xóa.
  • Map: Giao diện đại diện cho Collectionnơi mỗi phần tử có một "khóa" xác định - mỗi phần tử là một cặp khóa-giá trị.
    • HashMap: A Maptrong đó các khóa không được sắp xếp và được hỗ trợ bởi a Hashtable.
    • LinkedhashMap: Các phím được sắp xếp theo thứ tự chèn .
    • TreeMap: A Mapnơi các khóa được sắp xếp theo Comparatorthứ tự (thường là thứ tự tự nhiên).
  • Queue: Một giao diện đại diện cho một Collectionnơi mà các phần tử thường được thêm vào một đầu và bị xóa khỏi đầu kia (FIFO: nhập trước, xuất trước).
  • Stack: Một giao diện đại diện cho một Collectionphần tử, thông thường, cả được thêm (đẩy) và loại bỏ (bật) từ cùng một kết thúc (LIFO: nhập trước, xuất trước).
  • Deque: Viết tắt của "double queue queue", thường được phát âm là "boong". Một danh sách được liên kết thường chỉ được thêm vào và đọc từ một trong hai (không phải ở giữa).

Sơ đồ bộ sưu tập cơ bản:

biểu đồ

So sánh việc chèn một phần tử với một ArrayListLinkedList:

biểu đồ


2
Tốt nhất trong mùa hè ngắn gọn mà người ta có thể nhận được ở bất cứ đâu :)
roottraveller

11

Thậm chí hình ảnh đơn giản hơn là ở đây. Cố ý đơn giản hóa!

  1. Bộ sưu tập là bất cứ thứ gì chứa dữ liệu gọi là "phần tử" (cùng loại). Không có gì cụ thể hơn được giả định.

  2. Danh sách làtập hợp dữ liệu được lập chỉ mục trong đó mỗi phần tử có một chỉ mục. Một cái gì đó giống như mảng, nhưng linh hoạt hơn.

    Dữ liệu trong danh sách giữ thứ tự chèn.

    Hoạt động tiêu biểu: lấy phần tử thứ n.

  3. Set là một túi các phần tử , mỗi phần tử chỉ một lần (các phần tử được phân biệt bằngequals()phương thứccủa chúng.

    Dữ liệu trong tập được lưu trữ chủ yếu chỉ để biết những gì dữ liệu đang có.

    Hoạt động tiêu biểu: cho biết nếu một phần tử có mặt trong danh sách.

  4. Bản đồ là một cái gì đó giống như Danh sách, nhưng thay vì truy cập các phần tử theo chỉ số nguyên của chúng, bạn truy cập chúng bằng khóa của chúng, đó là bất kỳ đối tượng nào. Giống như mảng trong PHP :)

    Dữ liệu trong Bản đồ có thể tìm kiếm được bằng khóa của họ.

    Operaion điển hình: lấy một phần tử bằng ID của nó (trong đó ID thuộc bất kỳ loại nào, không chỉ intnhư trong trường hợp Danh sách).

Sự khác biệt

  • Set và Bản đồ: trong Set bạn tìm kiếm dữ liệu tự , trong khi trong Bản đồ của chính họ .

  • Danh sách và Bản đồ: trong Danh sách bạn truy cập phần tử theo intchỉ mục của chúng (vị trí trong Danh sách), trong khi trong Bản đồ theo khóa của chúng có os thuộc bất kỳ loại nào (thường là: ID)

  • List and Set: trong List, các phần tử bị ràng buộc bởi vị trí của chúng và có thể trùng lặp, trong khi trong Set, các phần tử chỉ là "hiện tại" (pr không có mặt) và là duy nhất (theo nghĩa của equals()hoặc compareTo()cho SortedSet)


1

Rất đơn giản: nếu bạn cần lưu trữ các giá trị với các khóa được ánh xạ tới chúng, hãy sử dụng giao diện Bản đồ, nếu không hãy sử dụng Danh sách cho các giá trị có thể bị trùng lặp và cuối cùng sử dụng giao diện Đặt nếu bạn không muốn các giá trị trùng lặp trong bộ sưu tập của mình.

Dưới đây là lời giải thích đầy đủ http://javatutorial.net/choose-the-right-java-collection , bao gồm cả sơ đồ, v.v.


1

Bản đồ

Nếu chọn một Map, tôi đã tạo bảng này tóm tắt các tính năng của từng trong số mười triển khai được gói cùng với Java 11.

Bảng triển khai bản đồ trong Java 11, so sánh các tính năng của chúng



-2

Tôi nên sử dụng Bộ sưu tập Java nào?

Nó phụ thuộc vào vấn đề bạn đang cố gắng giải quyết hoặc những yêu cầu bạn có.

Ví dụ:

  1. Bạn có muốn các yếu tố được sắp xếp trong khi lưu trữ chúng? Hashset
  2. Bạn có muốn các cặp (Khóa, Giá trị) được lưu trữ không? Bản đồ băm
  3. Bạn có muốn thứ tự của các yếu tố khi chèn được bảo tồn? ArrayList, LinkedList
  4. Bạn có muốn sắp xếp các cặp Khóa (Khóa, Giá trị) không? - văn bản mạnh mẽ
  5. Bạn có muốn thực hiện một Stack để giải quyết vấn đề của bạn? - Chồng
  6. Bạn có muốn có quyền truy cập FIFO (First in First out) không? - Hàng đợi
  7. Bạn có muốn chỉ lưu trữ các yếu tố ĐỘC ĐÁO? - Hashset
  8. Bạn có muốn cho phép khóa là "Không" trong khi lưu trữ (Khóa, Giá trị) không? - Bản đồ Hash
  9. Bạn có muốn không có giá trị NULL cho cặp (Khóa, Giá trị) không? HashTable

Ngay cả với văn bản mạnh mẽ trong mục 4 được thay thế bằng, giả sử, concurrencySkipListMap (K, V) , câu trả lời này thêm gì vào biểu đồ quyết định của Tim B , vào "mô tả danh sách ngắn" của aliteralmind ?
greybeard

Điểm đầu tiên của bạn, HashSet không sắp xếp dữ liệu, ngay cả thứ tự chèn cũng không được duy trì. Bạn nên thay đổi nó với Treeset
Saurabh Mishra
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.