JavaRush /Blog Java /Random-VI /Cấp độ 26. Trả lời các câu hỏi phỏng vấn về chủ đề cấp độ...
zor07
Mức độ
Санкт-Петербург

Cấp độ 26. Trả lời các câu hỏi phỏng vấn về chủ đề cấp độ. Phần 1. Câu hỏi 1-5, 10.

Xuất bản trong nhóm
Cấp độ 26. Trả lời các câu hỏi phỏng vấn về chủ đề cấp độ.  Phần 1. Câu hỏi 1-5, 10. - 1Phần tóm tắt khá rườm rà nên tôi chia làm hai phần. Phần thứ hai chứa câu trả lời cho các câu hỏi liên quan đến kankarency và đa luồng. Phần đầu tiên chứa phần còn lại. Viết khá khó khăn. Tôi vẫn chưa hiểu nhiều, nên như mọi khi, các nhận xét, nhận xét, bổ sung đều được chào đón)

1. Sử dụng giao diện Comparable như thế nào?

Giao diện Comparablechỉ khai báo một phương thức compareTo(Object obj), được thiết kế để thực hiện thứ tự của các đối tượng lớp. Nó thuận tiện để sử dụng khi sắp xếp danh sách hoặc mảng đối tượng theo thứ tự. Phương thức này so sánh đối tượng được gọi với obj. Ngược lại với phương thức equals, trả về true hoặc false , compareTotrả về:
  • 0 nếu các giá trị bằng nhau;
  • Giá trị âm nếu callee nhỏ hơn tham số;
  • Tích cực nếu callee lớn hơn tham số.
Nó chủ yếu hữu ích cho việc sắp xếp các danh sách có thứ tự ( java.util.List) và mảng các đối tượng. Nếu danh sách/mảng chứa các phần tử triển khai giao diện này thì chúng có thể được sắp xếp tự động theo tệp java.util.Collections.sort(List)/Arrays.sort(Object[]). Khái niệm về thứ tự tự nhiên được liên kết với một giao diện Comparable, bởi vì nó thiết lập một thứ tự tự nhiên cho các thể hiện của bất kỳ lớp nào triển khai giao diện này. Nói cách khác, thứ tự (x, y) tương ứng với việc thỏa mãn điều kiện x.compareTo(y) <= 0. Các quy tắc triển khai Comparable, hay đúng hơn là về phương thức của nó compareTo(Object)như sau (x và y là các thể hiện của lớp triển khai Comparable):
  • x.compareTo(y)trả về -1 hoặc 1 nếu x lần lượt ở trước hoặc sau y. Nếu phương thức trả về 0 thì thứ tự (x, y) và (y, x) là tương đương.
  • Nếu sign(a)là hàm trả về -1,0,1 cho a tương ứng nhỏ hơn 0, bằng 0 và lớn hơn 0 thì đẳng thức phải được thỏa mãn sign(x.compareTo(y))==-sign(y.compareTo(x)). Điều này rất logic: nếu x đứng trước y thì y phải đứng sau x và ngược lại.
  • Nếu x.compareTo(y) > 0y.compareTo(z) > 0, thì x.compareTo(z) > 0– mối quan hệ tính bắc cầu của bất đẳng thức.
  • Nếu x.compareTo(y) == 0, thì sign(x.compare(z)) == sign(y.compareTo(z)), với mọi z.
  • Cuộc gọi x.compareTo(null)phải đưa ra một ngoại lệ NullPointerException. Đây là sự khác biệt với logic triển khai equals(để tôi nhắc bạn, x.equals(null)nó trả về false ).
  • Nếu loại của y không thể so sánh được với x thì lệnh gọi x.compareTo(y)phải đưa ra một ngoại lệ ClassCastException.
  • (x.compareTo(y) == 0) == x.equals(y), I E. cuộc gọi x.compareTo(y)phải trả về 0 khi và chỉ khi x.equals(y)nó trả về true . Đây là một quy tắc nhất quán và rất quan trọng để xem xét.
Nguồn:

2. Sử dụng giao diện Comparator như thế nào?

Giao diện Comparatorkhai báo hai phương thức compare(Object obj1, Object obj2)equals(Object obj). Khi sử dụng giao diện Comparator, logic để so sánh một cặp đối tượng không bị ẩn bên trong lớp/đối tượng mà được triển khai trong một lớp riêng biệt. Phương pháp này compare(x,y)hoàn toàn giống với cuộc gọi x.compareTo(y). Tất cả các quy tắc phải được tuân theo chính xác giống như các quy tắc để triển khai một phương thức compareTo(Object)giao diện Comparable. Comparatorcó thể được sử dụng ở bất cứ nơi nào cần sắp xếp. Trong trường hợp này, trước hết, tính linh hoạt cần thiết xuất hiện - khả năng thực hiện một số quy tắc sắp xếp. Và thứ hai, các đối tượng đang được sắp xếp có thể không triển khai phương thức Comparable. Nếu họ thực hiện nó, Comparatornó sẽ được ưu tiên. Giao diện Comparatorcũng định nghĩa một phương thức equals(Object), nghe có vẻ nghịch lý. Phương thức này tự so sánh các phiên bản giao diện Comparatorvà chỉ trả về true nếu các đối tượng được so sánh có cùng thứ tự sắp xếp. Object.equals(Object)Tuy nhiên, việc giữ nguyên bản triển khai ban đầu luôn an toàn . Nguồn:

3. Lớp Collections có những phương thức nào?

public static <T> boolean addAll(Collection<? super T> c, T... elements) Phương thức này thêm các phần tử mảng elementsvào bộ sưu tập Collection<? super T> c. Các phần tử có thể được chỉ định riêng lẻ hoặc dưới dạng một mảng. Khi các phần tử được chỉ định riêng lẻ, phương pháp này cung cấp khả năng thêm tất cả các phần tử vào bộ sưu tập hiện có một cách thuận tiện: Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon"); public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) Cả hai phương pháp đều tìm kiếm danh sách được truyền trong tham số cho đối tượng được truyền trong tham số bằng thuật toán tìm kiếm nhị phân. Trả về chỉ mục của phần tử nếu có phần tử như vậy trong danh sách, nếu không thì chỉ mục của phần tử đầu tiên của danh sách lớn hơn key, nếu tất cả các phần tử nhỏ hơn key, trả về list.size(). Trước khi sử dụng các phương pháp này, danh sách phải được sắp xếp. Trong trường hợp đầu tiên, chúng được sắp xếp theo thứ tự tăng dần theo thứ tự “tự nhiên” của các thành phần trong danh sách (giống như khi sử dụng Collections.sort(list)). Trong trường hợp thứ hai, danh sách phải được sắp xếp theo thứ tự tăng dần theo thứ tự được cung cấp bởi bộ so sánh đã truyền (thứ tự tương tự như khi sử dụng Collections.sort(list, c)[ở đây "with" là bộ so sánh từ các tham số của phương thức được mô tả]) public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) Lời mở đầu: cơ chế generics trong ngôn ngữ cung cấp tính năng kiểm tra kiểu thời gian biên dịch. Thông thường điều này là đủ, nhưng có những lúc thì không. Ví dụ: chúng tôi chuyển bộ sưu tập của mình sang mã thư viện, một nơi nào đó mà chúng tôi không xác định và chúng tôi thực sự muốn mã của “thư viện bên thứ ba” này không chèn một phần tử sai loại vào bộ sưu tập của chúng tôi. Đây có thể là vấn đề số 1. Vấn đề có thể xảy ra số 2 là như sau. Giả sử chương trình của chúng tôi cung cấp cho chúng tôi một thông báo ClassCastException thông báo cho chúng tôi rằng một phần tử sai loại đã được chèn vào bộ sưu tập. Thật không may, ngoại lệ này có thể được đưa ra bất kỳ lúc nào sau khi một phần tử không chính xác được chèn vào và thường cung cấp cho chúng tôi rất ít hoặc không có thông tin nào về nguồn gốc của sự cố. Bằng cách sử dụng phương pháp phương pháp, checkedCollectionchúng ta có thể tự cứu mình khỏi vấn đề thứ nhất và thứ hai, bởi vì phương pháp này tạo ra một bộ sưu tập có thể kiểm chứng được khi chạy. Giải quyết vấn đề số hai bằng phương pháp này: Ví dụ: chúng ta có cái này và nó rơi ra ClassCastException.
Collection<String> c = new HashSet<String>();
Đoạn mã trên có thể tạm thời được thay thế bằng:
Collection<String> c = Collections.checkedCollection(
         new HashSet<String>(), String.class);
Khi chạy lại chương trình, chúng tôi bản địa hóa dòng mã chèn một phần tử không đúng loại vào bộ sưu tập của chúng tôi. Theo ý kiến ​​​​của tôi, các phương thức liên quan: public static <E> List<E> checkedList(List<E> list,Class<E> type) public static <K,V> Map<K,V> checkedMap(Map<K,V> m, Class<K> keyType,Class<V> valueType) public static <E> Set<E> checkedSet(Set<E> s,Class<E> type) public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K,V> m,Class<K> keyType,Class<V> valueType) public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,Class<E> type) public static <T> void copy(List<? super T> dest,List<? extends T> src) Phương thức sao chép các phần tử src vào dest. chỉ mục của các phần tử được sao chép sẽ giống nhau. public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) public static <T> T min(Collection<? extends T> coll,Comparator<? super T> comp) public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp) các phương thức trả về phần tử tối thiểu/tối đa trong bộ sưu tập theo “thứ tự tự nhiên” (Giao diện có thể so sánh) hoặc thứ tự của bộ so sánh đã qua. public static boolean disjoint(Collection<?> c1,Collection<?> c2) Trả về true nếu các bộ sưu tập không có phần tử giống hệt nhau. <T> List <T> emptyList(), <K,V> Map <K,V> emptyMap(), <T> Set <T> emptySet()– trả về một danh sách trống, bản đồ và tập hợp tương ứng; <T> void fill(List<? super T> list, T obj)– điền vào danh sách với phần tử đã cho; int frequency(Collection<?> c, Object o)– trả về số lần xuất hiện của một phần tử nhất định trong bộ sưu tập; <T> List <T> nCopies(int n, T o)– trả về danh sách n phần tử được chỉ định; <T> boolean replaceAll(List<T> list, T oldVal, T newVal)– thay thế tất cả các phần tử được chỉ định bằng phần tử mới; void reverse(List<?> list)– “đảo ngược” danh sách; void rotate(List<?> list, int distance)– thay đổi danh sách theo chu kỳ theo một số phần tử được chỉ định; void shuffle(List<?> list)– xáo trộn các phần tử trong danh sách; <T> Set <T> singleton(T o), singletonList(T o), singletonMap(K key, V value)– tạo một tập hợp, danh sách và hiển thị bản đồ bao gồm một phần tử; <T extends Comparable<? super T>> void sort(List<T> list), <T> void sort(List<T> list, Comparator<? super T> c)– sắp xếp danh sách theo thứ tự tự nhiên và sử dụng Comparatorcho phù hợp; void swap(List<?> list, int i, int j)– hoán đổi các phần tử danh sách tại các vị trí được chỉ định. Nguồn:

4. Lớp Arrays có những phương thức nào?

Bạn có thể xem danh sách đầy đủ các phương thức của lớp Arrays trong tài liệu . Trong bản tóm tắt này tôi sẽ chỉ trích dẫn một vài trong số đó. [đã dịch các phương pháp từ tài liệu và không may bị mất phần lớn bản dịch của tôi. Thật đáng tiếc và tôi không muốn lãng phí thời gian cho cùng một việc, vì vậy tôi sẽ dán những gì tôi đã tìm trên Google] public static <T> List<T> asList(T... a) để tạo một danh sách dựa trên một mảng. Mảng được sử dụng để biểu diễn nội bộ của danh sách. Điều này duy trì kết nối giữa danh sách và mảng ban đầu: những thay đổi trong mảng sẽ được phản ánh trong danh sách:
String[] a = { "foo", "bar", "baz"};
List<String> list = Arrays.asList(a);
System.out.println(list); // [foo, bar, baz]

a[0] = "aaa";
System.out.println(list); // [aaa, bar, baz]
những thay đổi trong danh sách sẽ được phản ánh trong mảng:
String[] a = { "foo", "bar", "baz"};
List<String> list = Arrays.asList(a);
System.out.println(list); // [foo, bar, baz]

list.set(0, "bbb");
System.out.println(Arrays.toString(a)); // [bbb, bar, baz]
Nếu mảng chứa các đối tượng, rõ ràng cả mảng và danh sách sẽ tham chiếu đến cùng một thể hiện:
Object[] a = { new Object(), new Object(), new Object()};
List<Object> list = Arrays.asList(a);
System.out.println(a[0] == list.get(0)); // true
int binarySearch(параметры)– một phương thức quá tải để tổ chức tìm kiếm nhị phân cho một giá trị trong mảng kiểu nguyên thủy và kiểu đối tượng. Trả về vị trí của trận đấu đầu tiên; void fill(параметры)– một phương thức quá tải để lấp đầy các mảng với các giá trị thuộc nhiều loại và nguyên thủy khác nhau; void Sort(parameters) – một phương thức quá tải để sắp xếp một mảng hoặc một phần của nó bằng cách sử dụng giao diện Comparator và không có nó; static <T> T[] copyOf(T[] original, int newLength)– điền vào một mảng có độ dài nhất định, loại bỏ các phần tử hoặc điền vào null nếu cần thiết; static <T> T[] copyOfRange(T[] original, int from, int to)– sao chép vùng xác định của mảng sang mảng mới; <T> List<T> asList(T… a)– một phương thức sao chép các phần tử mảng vào một đối tượng kiểu List<T>. Nguồn:

5. Tên của loại được sử dụng khi gọi Collections.sort() là gì?

Từ tài liệu : Việc triển khai là sự điều chỉnh của sắp xếp danh sách Python của Tim Peters (TimSort). Việc triển khai này chuyển danh sách vào một mảng, sắp xếp mảng, sau đó lặp qua danh sách và tải lại từng phần tử danh sách từ phần tử mảng tương ứng. Điều này tránh được sự phức tạp n*n log(n) có thể phát sinh khi cố gắng sắp xếp một danh sách liên kết trực tiếp Từ wiki : Timsort là một thuật toán sắp xếp kết hợp kết hợp sắp xếp chèn và sắp xếp hợp nhất, được xuất bản năm 2002 bởi Tim Peters. Timsort hiện là thuật toán sắp xếp tiêu chuẩn trong Python, OpenJDK 7 và được triển khai trong Android JDK 1.5. Ý tưởng chính của thuật toán là trong thế giới thực, các mảng dữ liệu có thể sắp xếp được thường chứa các mảng con có thứ tự. Trên dữ liệu như vậy, Timsort nhanh hơn đáng kể so với nhiều thuật toán sắp xếp.

10. Vòng lặp là gì?

Giao diện được giới thiệu trong bản phát hành JDK 1.2 của ngôn ngữ Java java.util.Iteratorcho phép lặp lại các lớp chứa. Mỗi Iterator triển khai các phương thức next()hasNext()có thể tùy chọn hỗ trợ tệp remove(). Các trình vòng lặp được tạo bởi các lớp chứa tương ứng, thường là bởi lớp iterator(). Phương thức này next()nâng trình vòng lặp lên giá trị tiếp theo và trả về giá trị đã chỉ định cho trình vòng lặp. Khi được tạo lần đầu, trình vòng lặp trỏ đến một giá trị đặc biệt trước phần tử đầu tiên, do đó phần tử đầu tiên chỉ có thể được truy xuất sau lệnh gọi đầu tiên tới next(). Để xác định thời điểm tất cả các phần tử trong vùng chứa đã được lặp lại, phương pháp thử nghiệm được sử dụng hasNext(). Ví dụ sau minh họa cách sử dụng đơn giản của các vòng lặp:
Iterator iter = list.iterator();
//Iterator<MyType> iter = list.iterator(); в J2SE 5.0
while (iter.hasNext())
    System.out.println(iter.next());
Đối với một bộ sưu tập kiểu hỗ trợ điều này, phương thức iterator remove()sẽ loại bỏ phần tử 'đã truy cập' cuối cùng khỏi vùng chứa. Hầu như tất cả các loại sửa đổi vùng chứa khác trong quá trình lặp lại đều không an toàn. Ngoài ra, for java.util.Listtồn tại java.util.ListIteratorvới một API tương tự, nhưng cho phép lặp tiến và lùi, cung cấp định nghĩa về chỉ mục hiện tại trong danh sách và di chuyển đến phần tử theo vị trí của nó. Nguồn: Phần 2
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION