1. Các tính năng liên quan đến Collection trong Java 8 là gì?
Java 8 đã mang lại những thay đổi lớn trong Collection API. Một số thay đổi là:
👉 Java Stream API cho các lớp collection để hỗ trợ xử lý tuần tự cũng như song song
👉 Iterable interface is extended with forEach() mà chúng ta có thể sử dụng để lặp qua một tập hợp. Nó rất hữu ích khi được sử dụng với lambda expressions vì đối số là Consumer là một function interface.
👉 Cải tiến Collection API khác như phương thức forEachRemaining (Hành động của người tiêu dùng) trong interface Iterator, các phương thức Map ReplaceAll(), compute(), merge().
2. Java Collections Framework là gì? Liệt kê một số lợi ích của Collections Framework?
Collection được sử dụng trong mọi ngôn ngữ lập trình và bản phát hành java ban đầu chứa một số lớp cho các Collection: Vector, Stack, Hashtable, Array. Nhưng nhìn vào phạm vi và cách sử dụng lớn hơn, Java 1.2 đã đưa ra Collections Framework nhóm tất cả các interface, triển khai và thuật toán của collection.
Java Collections đã trải qua một chặng đường dài với việc sử dụng các lớp Generics và Concurrent Collection cho các hoạt động an toàn luồng. Nó cũng bao gồm các interface chặn và triển khai của chúng trong gói đồng thời java. Một số lợi ích của collections framework là:
👉 Giảm nỗ lực phát triển bằng cách sử dụng các lớp thu thập cốt lõi thay vì triển khai các lớp thu thập của riêng chúng tôi.
👉 Chất lượng mã được nâng cao với việc sử dụng các lớp collections framework đã được kiểm tra tốt.
👉 Giảm nỗ lực bảo trì mã bằng cách sử dụng các lớp collection được vận chuyển cùng với JDK.
👉 Khả năng tái sử dụng và khả năng tương tác
3. Lợi ích của Generics trong Collections Framework là gì?
Java 1.5 đi kèm với Generics và tất cả các interface thu thập và triển khai đều sử dụng nó rất nhiều. Generics cho phép chúng tôi cung cấp loại Object mà một collection có thể chứa, vì vậy nếu bạn cố gắng thêm bất kỳ phần tử nào thuộc loại khác, nó sẽ gây ra lỗi compile time. Điều này tránh ClassCastException lúc Runtime vì bạn sẽ gặp lỗi khi biên dịch. Ngoài ra Generics làm cho mã sạch vì chúng ta không cần sử dụng toán tử casting và instanceof.
Tôi thực sự khuyên bạn nên xem qua Java Generic Tutorial để hiểu về số liệu chung theo cách tốt hơn.
4. Các interface cơ bản của Java Collections Framework là gì?
👉 Collection là gốc của hệ thống phân cấp collection. Một collection đại diện cho một nhóm các đối tượng được gọi là các phần tử của nó. Nền tảng Java không cung cấp bất kỳ triển khai trực tiếp nào của interface này.
👉 Set là collection không được chứa các phần tử trùng lặp. Interface này mô hình hóa sự trừu tượng tập hợp toán học và được sử dụng để đại diện cho các tập hợp, chẳng hạn như bộ bài.
👉 List là một tập hợp có thứ tự và có thể chứa các phần tử trùng lặp. Bạn có thể truy cập bất kỳ phần tử nào từ chỉ mục của nó. List giống như mảng với độ dài động.
👉 Một Map là một đối tượng mà các bản đồ chìa khóa để các giá trị. Map không được chứa các key trùng lặp: Mỗi key có thể ánh xạ đến nhiều nhất một giá trị.
Một số interface khác là Queue, Dequeue, Iterator, SortedSet, SortedMap và ListIterator.
5. Tại sao Collections không extends interface Cloneable và Serializable?
Collection interface chỉ định nhóm Object được gọi là phần tử. Việc các phần tử được duy trì như thế nào là tùy thuộc vào việc triển khai cụ thể của Collection. Ví dụ: một số triển khai Collection như List cho phép các phần tử trùng lặp trong khi các triển khai khác như Set thì không.
Rất nhiều triển khai Collection có phương pháp sao chép công khai. Tuy nhiên, không thực sự có ý nghĩa nếu bao gồm nó trong tất cả các triển khai của Collection. Điều này là do Collection là một biểu diễn trừu tượng. Điều quan trọng là việc thực hiện.
Ngữ nghĩa và ý nghĩa của việc nhân bản hoặc tuần tự hóa có tác dụng khi xử lý việc triển khai thực tế; vì vậy việc triển khai cụ thể nên quyết định cách nó nên được nhân bản hoặc đăng nhiều kỳ, hoặc thậm chí nếu nó có thể được nhân bản hoặc đăng nhiều kỳ.
Vì vậy, việc bắt buộc sao chép và tuần tự hóa trong tất cả các triển khai thực sự kém linh hoạt hơn và nhiều hạn chế hơn. Việc thực hiện cụ thể sẽ đưa ra quyết định liệu nó có thể được nhân bản hoặc đăng nhiều kỳ hay không.
Collection interface chỉ định nhóm Object được gọi là phần tử. Việc các phần tử được duy trì như thế nào là tùy thuộc vào việc triển khai cụ thể của Collection. Ví dụ: một số triển khai Collection như List cho phép các phần tử trùng lặp trong khi các triển khai khác như Set thì không.
Rất nhiều triển khai Collection có phương pháp sao chép công khai. Tuy nhiên, không thực sự có ý nghĩa nếu bao gồm nó trong tất cả các triển khai của Collection. Điều này là do Collection là một biểu diễn trừu tượng. Điều quan trọng là việc thực hiện.
Ngữ nghĩa và ý nghĩa của việc nhân bản hoặc tuần tự hóa có tác dụng khi xử lý việc triển khai thực tế; vì vậy việc triển khai cụ thể nên quyết định cách nó nên được nhân bản hoặc đăng nhiều kỳ, hoặc thậm chí nếu nó có thể được nhân bản hoặc đăng nhiều kỳ.
Vì vậy, việc bắt buộc sao chép và tuần tự hóa trong tất cả các triển khai thực sự kém linh hoạt hơn và nhiều hạn chế hơn. Việc thực hiện cụ thể sẽ đưa ra quyết định liệu nó có thể được nhân bản hoặc đăng nhiều kỳ hay không.
6. Tại sao Map interface không extend Collection interface?
Mặc dù Map interface và các triển khai của nó là một phần của Collection, Map không phải là collections và collections không phải là Map. Do đó, việc Map extends Collection hoặc ngược lại không có ý nghĩa gì.
Nếu Map extend Collection interface, thì các phần tử ở đâu? Map chứa các cặp key-value và nó cung cấp các phương thức để truy xuất danh sách Key hoặc Value dưới dạng Collection nhưng nó không phù hợp với mô hình “nhóm các phần tử”.
7. java8 Iterator là gì?
Interface Iterator cung cấp các phương thức để lặp qua bất kỳ Collection nào. Chúng ta có thể lấy thể hiện trình lặp từ một Collection bằng cách sử dụng phương thức iterator(). Iterator thay thế cho Enumeration Java Collections Framework. Trình lặp cho phép người gọi xóa các phần tử khỏi tập hợp cơ bản trong quá trình lặp. Trình vòng lặp Java Collection cung cấp một cách chung để duyệt qua các phần tử của một Collection và triển khai Iterator Design Pattern.
8. Sự khác biệt giữa Enumeration và interface Iterator là gì?
Enumeration nhanh gấp đôi so với Iterator và sử dụng rất ít bộ nhớ. Enumeration rất cơ bản và phù hợp với nhu cầu cơ bản. Nhưng Iterator an toàn hơn nhiều so với Enumeration vì nó luôn từ chối các luồng khác để sửa đổi đối tượng sưu tập đang được nó lặp lại.
Iterator thay thế cho Enumeration trong Java Collections Framework. Iterators cho phép người gọi loại bỏ các phần tử khỏi tập hợp cơ bản mà không thể thực hiện được với Enumeration. Tên phương thức Iterator đã được cải tiến để làm rõ chức năng của nó.
9. Tại sao không có phương thức như Iterator.add() để thêm các phần tử vào Collection?
Ngữ nghĩa không rõ ràng, vì hợp đồng cho Iterator không đảm bảo về thứ tự lặp lại. Tuy nhiên, lưu ý rằng ListIterator cung cấp một thao tác thêm, vì nó đảm bảo thứ tự của lần lặp.
10. Tại sao Iterator không có phương thức để lấy trực tiếp phần tử tiếp theo mà không cần di chuyển con trỏ?
Nó có thể được triển khai trên interface Iterator hiện tại nhưng vì việc sử dụng nó sẽ rất hiếm, nên không có ý nghĩa gì khi đưa nó vào interface mà mọi người phải triển khai.
11. Sự khác biệt giữa Iterator và ListIterator là gì?
👉 Chúng ta có thể sử dụng Iterator để duyệt qua các tập hợp Set và List trong khi ListIterator chỉ có thể được sử dụng với Lists.
👉 Iterator chỉ có thể đi qua theo hướng thuận trong khi ListIterator có thể được sử dụng để di chuyển theo cả hai hướng.
👉 ListIterator kế thừa từ interface Iterator và đi kèm với các chức năng bổ sung như thêm một phần tử, thay thế một phần tử, nhận vị trí chỉ mục cho các phần tử trước đó và tiếp theo.
12. Các cách khác nhau để lặp qua danh sách là gì?
Chúng ta có thể lặp lại danh sách theo hai cách khác nhau - sử dụng iterator và sử dụng vòng lặp for-each.
List<String>
strList = new ArrayList<>();
//using for-each loop for(String obj : strList){ System.out.println(obj);
}
//using iterator
Iterator<String> it = strList.iterator(); while(it.hasNext()){ String obj = it.next();
System.out.println(obj);
}
strList = new ArrayList<>();
//using for-each loop for(String obj : strList){ System.out.println(obj);
}
//using iterator
Iterator<String> it = strList.iterator(); while(it.hasNext()){ String obj = it.next();
System.out.println(obj);
}
Sử dụng iterator sẽ an toàn hơn vì nó đảm bảo rằng nếu các phần tử danh sách cơ bản được sửa đổi, nó sẽ ném ConcurrentModificationException.
13. Bạn hiểu gì về thuộc tính fail-fast của iterator?
iterator fail-fast kiểm tra thuộc tính fail-fast để tìm bất kỳ sửa đổi nào trong cấu trúc của collection cơ bản mỗi khi chúng tôi cố gắng lấy phần tử tiếp theo. Nếu có bất kỳ sửa đổi nào được tìm thấy, nó sẽ ném ConcurrentModificationException. Tất cả các triển khai của Iterator trong các lớp collection đều fail-fast theo thiết kế ngoại trừ các lớp thu thập đồng thời như ConcurrentHashMap và CopyOnWriteArrayList.
14. Sự khác biệt giữa fail-fast và fail-safe là gì?
Thuộc tính fail-safe của Iterator hoạt động với bản sao của Collection cơ bản, do đó nó không bị ảnh hưởng bởi bất kỳ sửa đổi nào trong Collection . Theo thiết kế, tất cả các lớp Collection trong gói java.util là fail-fast trong khi các lớp Collection trong java.util.concurrent là an toàn.
Trình vòng lặp nhanh không thành công ném ConcurrentModificationException trong khi trình vòng lặp fail-safe không bao giờ ném ConcurrentModificationException.
Kiểm tra bài đăng này để biết CopyOnWriteArrayList Example.
15 .Làm cách nào để tránh ConcurrentModificationException trong khi lặp lại một Collection?
Chúng ta có thể sử dụng các lớp Concurrent Collection để tránh ConcurrentModificationException trong khi lặp qua một Collection, ví dụ CopyOnWriteArrayList thay vì ArrayList. Kiểm tra bài đăng này để biết ConcurrentHashMap Example.
16. Tại sao không có triển khai cụ thể của interface Iterator?
Interface Iterator khai báo các phương thức để lặp lại một Collection nhưng việc triển khai nó là trách nhiệm của các lớp triển khai Collection. Mỗi lớp collection trả về một trình vòng lặp để duyệt qua đều có lớp lồng nhau triển khai Iterator của riêng nó. Điều này cho phép các lớp collection chọn xem trình lặp là nhanh hay không an toàn. Ví dụ: trình lặp ArrayList là fail-fast trong khi trình lặp CopyOnWriteArrayList là fail-safe.
17. UnsupportedOperationException là gì?
UnsupportedOperationException là ngoại lệ được sử dụng để chỉ ra rằng hoạt động không được hỗ trợ. Nó được sử dụng rộng rãi trong các lớp JDK , trong Collection Framework java.util.Collections. UnmodifiableCollection ném ngoại lệ này cho tất cả các thao tác thêm và bớt.
18. HashMap hoạt động như thế nào trong Java?
HashMap lưu trữ cặp Key-Value trong Map. Entry triển khai static nested class. HashMap hoạt động trên thuật toán băm và sử dụng phương thức hashCode() và equals() trong các phương thức put và get.
Khi chúng ta gọi phương thức put bằng cách truyền cặp Key-Value, HashMap sử dụng Key hashCode() với hàm băm để tìm ra chỉ mục lưu trữ cặp Key-Value. Entry(mục nhập) được lưu trữ trong LinkedList, vì vậy nếu đã có mục nhập hiện có, nó sử dụng phương thức equals() để kiểm tra xem Key được truyền đã tồn tại chưa, nếu có, nó sẽ ghi đè giá trị khác, nó sẽ tạo mục nhập mới và lưu trữ mục nhập Key-Value này.
Khi chúng ta gọi phương thức get bằng cách truyền Key, một lần nữa nó sử dụng hashCode() để tìm chỉ mục trong mảng và sau đó sử dụng phương thức equals() để tìm Entry chính xác và trả về giá trị của nó. Hình ảnh dưới đây sẽ giải thích rõ ràng những chi tiết này.

Những điều quan trọng khác cần biết về HashMap là dung lượng, hệ số tải, thay đổi kích thước ngưỡng. Dung lượng mặc định ban đầu của HashMap là 16 và hệ số tải là 0,75. Ngưỡng là dung lượng nhân với hệ số tải và bất cứ khi nào chúng tôi cố gắng thêm một mục nhập, nếu kích thước Map lớn hơn ngưỡng, HashMap sẽ nhấn mạnh lại nội dung của Map thành một mảng mới có dung lượng lớn hơn. Dung lượng luôn là lũy thừa của 2, vì vậy nếu bạn biết rằng bạn cần lưu trữ một số lượng lớn các cặp key-value, chẳng hạn như trong bộ nhớ đệm dữ liệu từ cơ sở dữ liệu, bạn nên khởi tạo HashMap với dung lượng và hệ số tải chính xác.
19. Tầm quan trọng của phương thức hashCode() và equals() là gì?
HashMap sử dụng phương thức Key đối tượng hashCode() và equals() để xác định chỉ số để đặt cặp Key-Value. Các phương pháp này cũng được sử dụng khi chúng tôi cố gắng lấy giá trị từ HashMap.
Nếu các phương thức này không được triển khai chính xác, hai Key khác nhau có thể tạo ra cùng một đầu ra hashCode() và equals() và trong trường hợp đó, thay vì lưu trữ nó ở vị trí khác, HashMap sẽ coi chúng giống nhau và ghi đè chúng.
Tương tự như vậy, tất cả các lớp thu thập không lưu trữ dữ liệu trùng lặp sử dụng hashCode() và equals() để tìm các bản sao, vì vậy điều rất quan trọng là phải triển khai chúng một cách chính xác. Việc triển khai equals() và hashCode() phải tuân theo các quy tắc này.
👉 Nếu o1.equals(o2), thì o1.hashCode() == o2.hashCode() luôn luôn là true.
👉 Nếu o1.hashCode() == o2.hashCode là true, nó không có nghĩa rằng o1.equals(o2) sẽ là true.
20. Chúng ta có thể sử dụng bất kỳ lớp nào làm key của Map không?
Chúng ta có thể sử dụng bất kỳ lớp nào làm Map Key, tuy nhiên cần cân nhắc những điểm sau trước khi sử dụng chúng.
👉 Nếu lớp ghi đè phương thức equals(), nó cũng sẽ ghi đè phương thức hashCode().
👉 Lớp phải tuân theo các quy tắc được liên kết với equals() và hashCode() cho tất cả các trường hợp. Vui lòng tham khảo câu hỏi trước đó cho các quy tắc này.
👉 Nếu một trường lớp không được sử dụng trong equals(), bạn không nên sử dụng nó trong phương thức hashCode().
👉 Phương pháp hay nhất đối với lớp Key do người dùng xác định là làm cho nó trở nên bất biến, để giá trị hashCode() có thể được lưu vào bộ nhớ đệm để có hiệu suất nhanh. Ngoài ra, các lớp không thay đổi đảm bảo rằng hashCode() và equals() sẽ không thay đổi trong tương lai, điều này sẽ giải quyết bất kỳ vấn đề nào với khả năng thay đổi.
Ví dụ: giả sử tôi có một lớp MyKey mà tôi đang sử dụng cho khóa HashMap.
// Đối số tên MyKey
đã truyền được sử dụng cho equals ( ) và hashCode ()
MyKey key = new MyKey("itech"); //assume hashCode=1234 myHashMap.put(key, "Value");
// Đoạn mã dưới đây sẽ thay đổi khóa hashCode ( ) và bằng
()
// nhưng vị trí của nó không bị thay đổi.
key.setName("Amit"); // giả sử hashCode mới
= 7890
// bên dưới sẽ trả về null, vì HashMap sẽ cố gắng tìm kiếm khóa
// trong cùng một chỉ mục như nó đã được lưu trữ nhưng vì khóa bị biến
đổi,
// sẽ không có kết quả phù hợp và nó sẽ trả về null.
myHashMap.get(new MyKey("itech "));
21. Các chế độ xem Collection khác nhau được cung cấp bởi Map interface là gì?
Map interface cung cấp ba chế độ xem Collection:
👉 Set keySet(): Trả về chế độ xem Set of keys có trong Map này. Set được Map hỗ trợ, vì vậy các thay đổi đối với Map được phản ánh trong Set và ngược lại. Nếu Map được sửa đổi trong khi một lần lặp trên Set đang diễn ra (ngoại trừ thông qua hoạt động xóa của chính trình lặp), kết quả của lần lặp là không xác định. Set hỗ trợ loại bỏ phần tử, loại bỏ ánh xạ tương ứng khỏi Map, thông qua các hoạt động Iterator.remove, Set.remove, removeAll, keepAll và delete. Nó không hỗ trợ các hoạt động add hoặc addAll.
👉 Collection values(): Trả về dạng xem Collection of Values có trong Map này. Collection được hỗ trợ bởi Map, vì vậy các thay đổi đối với Map được phản ánh trong Collection và ngược lại. Nếu Map được sửa đổi trong khi quá trình lặp lại Collection đang diễn ra (ngoại trừ thông qua hoạt động xóa của chính trình lặp), kết quả của lần lặp là không xác định. Collection hỗ trợ loại bỏ phần tử, loại bỏ ánh xạ tương ứng khỏi Map, thông qua các hoạt động Iterator.remove, Set.remove, removeAll, keepAll và delete. Nó không hỗ trợ các hoạt động add hoặc addAll.
👉 Set<Map.Entry<K, V>> entrySet(): Trả về dạng xem Set của các ánh xạ có trong bản đồ này. Set được Map hỗ trợ, vì vậy các thay đổi đối với Map được phản ánh trong Set và ngược lại. Nếu Map được sửa đổi trong khi quá trình lặp lại trên tập hợp đang diễn ra (ngoại trừ thông qua hoạt động xóa của chính trình lặp hoặc thông qua hoạt động setValue trên mục nhập Map do trình lặp trả về) thì kết quả của phép lặp là không xác định. Set hỗ trợ loại bỏ phần tử, loại bỏ ánh xạ tương ứng khỏi Map, thông qua các hoạt động Iterator.remove, Set.remove, removeAll, keepAll và delete. Nó không hỗ trợ các hoạt động add hoặc addAll.
[sociallocker id = ”2713 ″]
22. Sự khác biệt giữa HashMap và Hashtable?
HashMap và Hashtable đều triển khai Map interface và trông giống nhau, tuy nhiên có sự khác biệt sau đây giữa HashMap và Hashtable.
👉 HashMap cho phép Key-Value rỗng trong khi Hashtable không cho phép Key-Value rỗng.
👉 Hashtable được đồng bộ hóa nhưng HashMap không được đồng bộ hóa. Vì vậy HashMap tốt hơn cho môi trường đơn luồng, Hashtable phù hợp với môi trường đa luồng.
👉 LinkedHashMap đã được giới thiệu trong Java 1.4 như một lớp con của HashMap, vì vậy trong trường hợp bạn muốn thứ tự lặp, bạn có thể dễ dàng chuyển từ HashMap sang LinkedHashMap nhưng đó không phải là trường hợp với Hashtable có thứ tự lặp là không thể đoán trước.
👉 HashMap cung cấp Set of keys và do đó nó không nhanh nhưng Hashtable cung cấp Enumeration of keys không hỗ trợ tính năng này.
👉 Hashtable được coi là lớp kế thừa và nếu bạn đang tìm kiếm các sửa đổi của Map trong khi lặp, bạn nên sử dụng ConcurrentHashMap.
23. Làm thế nào để phân biệt giữa HashMap và TreeMap?
Để chèn, xóa và định vị các phần tử trong Map, HashMap cung cấp giải pháp thay thế tốt nhất. Tuy nhiên, nếu bạn cần duyệt qua các key theo thứ tự được sắp xếp, thì TreeMap là lựa chọn thay thế tốt hơn cho bạn. Tùy thuộc vào kích thước bộ sưu tập của bạn, có thể nhanh hơn để thêm các phần tử vào HashMap, sau đó chuyển đổi bản đồ thành TreeMap để duyệt qua khóa được sắp xếp.
24. Điểm giống và khác nhau giữa ArrayList và Vector?
ArrayList và Vector là các lớp tương tự nhau theo nhiều cách.
👉 Cả hai đều dựa trên chỉ mục và được sao lưu bởi một mảng trong nội bộ.
👉 Cả hai đều duy trì thứ tự chèn và chúng ta có thể nhận được các phần tử theo thứ tự chèn.
👉 Việc triển khai trình lặp của ArrayList và Vector đều không nhanh theo thiết kế.
👉 ArrayList và Vector đều cho phép các giá trị null và truy cập ngẫu nhiên vào phần tử sử dụng số chỉ mục.
Đây là những khác biệt giữa ArrayList và Vector.
👉 Vector được đồng bộ hóa trong khi ArrayList không được đồng bộ hóa. Tuy nhiên, nếu bạn đang tìm cách sửa đổi danh sách trong khi lặp, bạn nên sử dụng CopyOnWriteArrayList.
👉 ArrayList nhanh hơn Vector vì nó không có bất kỳ chi phí nào do đồng bộ hóa.
👉 ArrayList linh hoạt hơn vì chúng ta có thể lấy danh sách đồng bộ hoặc danh sách chỉ đọc từ nó một cách dễ dàng bằng cách sử dụng lớp tiện ích Collections.
25. Sự khác biệt giữa Array và ArrayList là gì? Khi nào bạn sẽ sử dụng Array trên ArrayList?
Array có thể chứa các đối tượng hoặc nguyên thủy trong khi ArrayList chỉ có thể chứa các Object. Array có kích thước cố định trong khi kích thước ArrayList là động.
Array không cung cấp nhiều tính năng như ArrayList, chẳng hạn như addAll, removeAll, iterator, v.v.
Mặc dù ArrayList là sự lựa chọn rõ ràng khi chúng ta làm việc trên danh sách, nhưng có rất ít khi mảng này tốt để sử dụng.
👉 Nếu kích thước của danh sách là cố định và chủ yếu được sử dụng để lưu trữ và duyệt qua chúng.
👉 Đối với danh sách các kiểu dữ liệu nguyên thủy, mặc dù Collection sử dụng autoboxing để giảm nỗ lực mã hóa nhưng nó vẫn khiến chúng chậm khi làm việc trên các kiểu dữ liệu nguyên thủy có kích thước cố định.
👉 Nếu bạn đang làm việc với tình huống đa chiều cố định, việc sử dụng [] [] dễ dàng hơn nhiều so với List <List <>>
26. Sự khác biệt giữa ArrayList và LinkedList là gì?
ArrayList và LinkedList đều triển khai List Interface nhưng có một số khác biệt giữa chúng.
👉 ArrayList là một cấu trúc dữ liệu dựa trên chỉ mục được hỗ trợ bởi Array, vì vậy nó cung cấp quyền truy cập ngẫu nhiên vào các phần tử của nó với hiệu suất là O (1) nhưng LinkedList lưu trữ dữ liệu dưới dạng danh sách các nút trong đó mọi nút được liên kết với nút trước và nút tiếp theo của nó. Vì vậy, mặc dù có một phương thức để lấy phần tử bằng cách sử dụng chỉ mục, bên trong nó di chuyển từ đầu đến đến tại nút chỉ mục và sau đó trả về phần tử, do đó hiệu suất là O(n) chậm hơn ArrayList.
👉 Chèn, thêm hoặc bớt một phần tử nhanh hơn trong LinkedList so với ArrayList vì không có khái niệm thay đổi kích thước mảng hoặc cập nhật chỉ mục khi phần tử được thêm vào giữa.
👉 LinkedList tiêu tốn nhiều bộ nhớ hơn ArrayList vì mọi nút trong LinkedList đều lưu trữ tham chiếu của các phần tử trước đó và tiếp theo.
27. Collection classes nào cung cấp quyền truy cập ngẫu nhiên các phần tử của nó?
Các lớp ArrayList, HashMap, TreeMap, Hashtable cung cấp quyền truy cập ngẫu nhiên vào các phần tử của nó.
Tải xuống java collections pdf để biết thêm thông tin.
28. EnumSet là gì?
java.util.EnumSet là Set triển khai để sử dụng với các kiểu enum. Tất cả các phần tử trong một tập hợp enum phải đến từ một kiểu enum duy nhất được chỉ định, rõ ràng hoặc ngầm định, khi tập hợp được tạo. EnumSet không được đồng bộ hóa và các phần tử rỗng không được phép. Nó cũng cung cấp một số phương thức hữu ích như copyOf ( Collection c), of(E first, E… rest) và complementOf(EnumSet s).
Kiểm tra bài đăng này để biết java enum tutorial.
29. Các lớp tập hợp nào là an toàn cho luồng?
Vector, Hashtable, Properties và Stack là các lớp được đồng bộ hóa, vì vậy chúng an toàn theo luồng và có thể được sử dụng trong môi trường đa luồng. Java 1.5 Concurrent API bao gồm một số lớp collection cho phép sửa đổi collection trong khi lặp lại vì chúng hoạt động trên bản sao của colletion, vì vậy chúng an toàn khi sử dụng trong môi trường đa luồng.
30. Collection Classes đồng thời là gì?
Java 1.5 Concurrent package (java.util.concurrent) chứa các lớp thu thập an toàn theo luồng cho phép các tập hợp được sửa đổi trong khi lặp. Theo thiết kế, việc triển khai Iterator trong các gói java.util không nhanh và ném ra ConcurrentModificationException. Nhưng việc triển khai Iterator trong các gói java.util.concurrent là không an toàn và chúng ta có thể sửa đổi bộ sưu tập trong khi lặp lại. Một số lớp này là CopyOnWriteArrayList, ConcurrentHashMap, CopyOnWriteArraySet.
Đọc những bài đăng này để tìm hiểu về chúng chi tiết hơn.
Avoid ConcurrentModificationException
CopyOnWriteArrayList Example
HashMap vs ConcurrentHashMap
31. BlockingQueue là gì?
java.util.concurrent.BlockingQueue là một Queue hỗ trợ các hoạt động đợi hàng đợi trở nên không trống khi truy xuất và xóa một phần tử, và đợi khoảng trống có sẵn trong hàng đợi khi thêm một phần tử.
Interface BlockingQueue là một phần của java collections framework và nó chủ yếu được sử dụng để thực hiện vấn đề người sử dụng của nhà sản xuất. Chúng ta không cần phải lo lắng về việc chờ đợi không gian có sẵn cho nhà sản xuất hoặc đối tượng có sẵn cho người dùng trong BlockingQueue vì nó được xử lý bởi các lớp triển khai của BlockingQueue.
Java cung cấp một số triển khai BlockingQueue như ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue, v.v.
Kiểm tra bài đăng này để sử dụng BlockingQueue cho producer-consumer problem.
34. Comparable và Comparator interface?
Java cung cấp Comparable interface sẽ được thực hiện bởi bất kỳ lớp tùy chỉnh nào nếu chúng ta muốn sử dụng các phương pháp sắp xếp Array hoặc Collection. Comparable interface có phương thức CompareTo( T obj) được sử dụng bởi các phương pháp sắp xếp. Chúng ta nên ghi đè phương thức này theo cách mà nó trả về một số nguyên âm, 0 hoặc một số nguyên dương nếu đối tượng “this” nhỏ hơn, bằng hoặc lớn hơn đối tượng được truyền dưới dạng đối số.
Tuy nhiên, trong hầu hết các tình huống thực tế, chúng tôi muốn sắp xếp dựa trên các tham số khác nhau. Ví dụ, với tư cách là CEO, tôi muốn sắp xếp nhân viên dựa trên Mức lương, nhân sự muốn sắp xếp họ dựa trên độ tuổi. Đây là tình huống mà chúng ta cần sử dụng Comparator interface vì việc triển khai phương thức Comparable.compareTo(Object o) có thể sắp xếp chỉ dựa trên một trường và chúng ta không thể chọn trường mà chúng ta muốn sắp xếp Object.
Phương thức Comparator interface compare(Object o1, Object o2) cần được triển khai có nhận hai đối số Object, nó phải được triển khai theo cách mà nó trả về giá trị nguyên âm nếu đối số đầu tiên nhỏ hơn đối số thứ hai và trả về 0 nếu chúng bằng nhau và int dương nếu đối số đầu tiên lớn hơn đối số thứ hai.
Kiểm tra bài đăng này để sử dụng Comparable and Comparator interface để sort objects.
32. Queue và Stack là gì, liệt kê sự khác biệt của chúng?
Cả Queue và Stack đều được sử dụng để lưu trữ dữ liệu trước khi xử lý chúng java.util.Queue là một interface có các lớp triển khai có trong gói đồng thời java. Hàng đợi cho phép truy xuất phần tử theo thứ tự First-In-First-Out (FIFO) nhưng không phải lúc nào cũng vậy. Ngoài ra còn có interface Deque cho phép các phần tử được truy xuất từ cả hai phần cuối của hàng đợi.
Stack tương tự như hàng đợi ngoại trừ nó cho phép các phần tử được truy xuất theo thứ tự Last-In-First-Out (LIFO).
Stack là một lớp mở rộng Vector trong khi Queue là một interface.
33. Class Collections là gì?
java.util.Collections là một lớp tiện ích chỉ bao gồm các phương thức static hoạt động trên hoặc trả về các collection. Nó chứa các thuật toán đa hình hoạt động trên các collection, “wrappers”, trả về một tập hợp mới được hỗ trợ bởi một tập hợp cụ thể, và một số tỷ lệ cược và kết thúc khác.
Lớp này chứa các phương thức cho các thuật toán collection framework, chẳng hạn như tìm kiếm nhị phân, sắp xếp, xáo trộn, đảo ngược, v.v.
35. Sự khác biệt giữa Comparable và Comparator interface là gì?
👉 Comparable và Comparator interface được sử dụng để sắp xếp tập hợp hoặc mảng các đối tượng.
👉 Comparable interface được sử dụng để cung cấp khả năng sắp xếp tự nhiên của các đối tượng và chúng ta có thể sử dụng nó để cung cấp phân loại dựa trên logic đơn.
· Comparator interface được sử dụng để cung cấp các thuật toán khác nhau để sắp xếp và chúng ta có thể chọn bộ so sánh mà chúng ta muốn sử dụng để sắp xếp tập hợp các đối tượng đã cho.
36. Làm thế nào chúng ta có thể sắp xếp một danh sách các Object?
Nếu chúng ta cần sắp xếp một mảng các Object, chúng ta có thể sử dụng Arrays.sort(). Nếu chúng ta cần sắp xếp một danh sách các đối tượng, chúng ta có thể sử dụng Collections.sort(). Cả hai lớp này đều có các phương thức sort() được nạp chồng để sắp xếp tự nhiên (sử dụng Comparable) hoặc sắp xếp dựa trên tiêu chí (sử dụng Comparator). Collection sử dụng nội bộ phương pháp Array sort, vì vậy cả hai đều có hiệu suất như nhau ngoại trừ việc Collection mất một lúc để chuyển đổi danh sách thành mảng.
37. Trong khi truyền một đối số là Collection cho một hàm, làm thế nào chúng ta có thể đảm bảo rằng hàm sẽ không thể sửa đổi nó?
Chúng tôi có thể tạo một collection chỉ đọc bằng cách sử dụng phương thức Collections.unmodifiableCollection (Collection c) trước khi chuyển nó làm đối số, điều này sẽ đảm bảo rằng bất kỳ thao tác nào để thay đổi collection sẽ ném ra UnsupportedOperationException.
38. Làm thế nào chúng ta có thể tạo một collection đồng bộ từ collection đã cho?
Chúng ta có thể sử dụng Collections.synchronizedCollection (Collection c) để có được một bộ sưu tập được đồng bộ hóa (an toàn theo luồng) được hỗ trợ bởi collection đã chỉ định.
39. Các thuật toán phổ biến được thực hiện trong Collections Framework là gì?
Java Collections Framework cung cấp các triển khai thuật toán thường được sử dụng như sắp xếp và tìm kiếm. Lớp Collections chứa các triển khai phương thức này. Hầu hết các thuật toán này hoạt động trên List nhưng một số trong số chúng có thể áp dụng cho tất cả các loại tập hợp.
Một số trong số đó là sắp xếp, tìm kiếm, xáo trộn, giá trị tối thiểu.
40. Ký hiệu Big-O là gì? Đưa ra vài ví dụ?
Ký hiệu Big-O mô tả hiệu suất của một thuật toán về số lượng phần tử trong cấu trúc dữ liệu. Vì các lớp Collection thực sự là cấu trúc dữ liệu, chúng ta thường có xu hướng sử dụng ký hiệu Big-O để chọn việc triển khai Collection để sử dụng dựa trên thời gian, bộ nhớ và hiệu suất.
Ví dụ 1: ArrayList get(index i) là một phép toán thời gian không đổi và không phụ thuộc vào số phần tử trong danh sách. Vì vậy, hiệu suất của nó trong ký hiệu Big-O là O (1). Ví dụ 2: Tìm kiếm tuyến tính trên mảng hoặc hiệu suất danh sách là O(n) vì chúng ta cần tìm kiếm trong toàn bộ danh sách các phần tử để tìm phần tử.
41. Các phương pháp hay nhất liên quan đến Java Collections Framework là gì?
👉 Chọn loại tập hợp phù hợp dựa trên nhu cầu, ví dụ nếu kích thước được cố định, chúng ta có thể muốn sử dụng Array thay vì ArrayList. Nếu chúng ta phải lặp lại Map theo thứ tự chèn, chúng ta cần sử dụng TreeMap. Nếu chúng ta không muốn trùng lặp, chúng ta nên sử dụng Set.
👉 Một số lớp collection cho phép chỉ định dung lượng ban đầu, vì vậy nếu chúng ta có ước tính số lượng phần tử sẽ lưu trữ, chúng ta có thể sử dụng nó để tránh băm lại hoặc thay đổi kích thước.
👉 Viết chương trình trong điều kiện interface không phải hiện thực, nó cho phép chúng ta thay đổi việc triển khai một cách dễ dàng tại thời điểm sau này.
👉 Luôn sử dụng Generics để đảm bảo an toàn cho kiểu và tránh ClassCastException trong thời gian chạy.
👉 Sử dụng các lớp không thay đổi được cung cấp bởi JDK làm khóa trong Map để tránh triển khai hashCode() và equals() cho lớp tùy chỉnh của chúng tôi.
👉 Sử dụng lớp tiện ích Collections càng nhiều càng tốt cho các thuật toán hoặc để nhận các Collection chỉ đọc, đồng bộ hóa hoặc trống hơn là viết triển khai riêng. Nó sẽ tăng cường khả năng tái sử dụng mã với độ ổn định cao hơn và khả năng bảo trì thấp.
42. Java Priority Queue là gì?
PriorityQueue là một hàng đợi không bị ràng buộc dựa trên một đống ưu tiên và các phần tử được sắp xếp theo thứ tự tự nhiên của chúng hoặc chúng tôi có thể cung cấp Comparator để sắp xếp thứ tự tại thời điểm tạo.
PriorityQueue không cho phép giá trị rỗng và chúng tôi không thể thêm bất kỳ đối tượng nào không cung cấp thứ tự tự nhiên hoặc chúng tôi không có bất kỳ comparator nào cho chúng để sắp xếp. Java PriorityQueue không phải là luồng - an toàn và được cung cấp thời gian O(log (n)) cho các hoạt động xếp và tách. Kiểm tra bài đăng này để biết java priority queue example.
43. Tại sao chúng ta không thể viết mã dưới dạng List <Number> number = new ArrayList <Integer >();?
Generics không hỗ trợ nhập phụ vì nó sẽ gây ra các vấn đề trong việc đạt được độ an toàn khi nhập. Đó là lý do tại sao List <T> không được coi là một kiểu con của List <S> trong đó S là super-type của T. Để hiểu tại sao nó không được phép, hãy xem điều gì có thể xảy ra nếu nó được hỗ trợ.
List <Long> listLong = new ArrayList < Long >
( );
listLong.add (Long. valueOf (10));
List <Number> listNumbers =
listLong; // lỗi trình biên dịch
listNumbers.add (Double.valueOf ( 1.23 ));
Như bạn có thể thấy từ mã trên rằng IF generics sẽ hỗ trợ nhập phụ, chúng ta có thể dễ dàng thêm Double vào danh sách Long sẽ gây ra ClassCastException trong runtime trong khi duyệt qua danh sách Long.
44. Tại sao chúng ta không thể tạo mảng chung? Hoặc viết mã dưới dạng List <Integer > [ ] array = new ArrayList <Integer> [10];
Chúng tôi không được phép tạo mảng chung vì mảng mang thông tin loại của các phần tử của nó trong thời gian chạy. Thông tin này được sử dụng trong thời gian chạy để ném ArrayStoreException nếu kiểu phần tử không khớp với kiểu đã xác định. Vì thông tin loại generics bị xóa trong thời gian chạy bởi Type Erasure, kiểm tra lưu trữ mảng sẽ được vượt qua nơi đáng lẽ không thành công. Hãy hiểu điều này với một mã ví dụ đơn giản.
List < Integer > [ ] intList = new List< Integer > [ 5 ]; // Lỗi biên dịch
Object [ ] objArray = intList;
List <Double> doubleList = new ArrayList <Double > ( );
doubleLis. add (Double. valueOf ( 1.23 ));
objArray [ 0 ] = doubleList; // điều này sẽ không thành công nhưng nó sẽ vượt qua vì trong runtime intList và doubleList cả hai đều chỉ là List
Object [ ] objArray = intList;
List <Double> doubleList = new ArrayList <Double > ( );
doubleLis. add (Double. valueOf ( 1.23 ));
objArray [ 0 ] = doubleList; // điều này sẽ không thành công nhưng nó sẽ vượt qua vì trong runtime intList và doubleList cả hai đều chỉ là List
Mảng là hiệp phương sai về bản chất, tức là S [ ] là một kiểu con của T [] bất cứ khi nào S là một kiểu con của T nhưng phần chung không hỗ trợ hiệp phương sai hoặc gõ con như chúng ta đã thấy trong câu hỏi trước. Vì vậy, nếu chúng ta được phép tạo các mảng chung, vì xóa kiểu, chúng ta sẽ không nhận được ngoại lệ lưu trữ mảng mặc dù cả hai kiểu không liên quan. Để biết thêm về Generics, hãy đọc Java Generics Tutorial.
Bài viết được dịch lại từ journaldev.com. Cảm ơn bạn đã xem bài viết!
Nếu có bất cứ lỗi sai nào trong bài bạn có thể góp ý cho chúng tôi bằng cách bình luận bên dưới.

0 Nhận xét