JavaRush /Java блог /Random UA /Рівень 26. Відповіді питання до співбесіди на тему рівня....
zor07
31 рівень
Санкт-Петербург

Рівень 26. Відповіді питання до співбесіди на тему рівня. Частина 1. Запитання 1-5, 10.

Стаття з групи Random UA
Рівень 26. Відповіді питання до співбесіди на тему рівня.  Частина 1. Запитання 1-5, 10. - 1Конспект вийшов досить громіздким, тож поділив його на дві частини. У другій частині зібрані відповіді на питання щодо канкаренсі та багатопоточності. У першій частині решта. Написання далося досить важко. Багато чого все одно не розумію, тому як завжди, коментарі, зауваження, доповнення – вітаються)

1. Як користуватись інтерфейсом Comparable?

В інтерфейсі Comparableоголошено лише один метод compareTo(Object obj), призначений для реалізації впорядкування об'єктів класу. Його зручно використовувати при сортуванні впорядкованих списків чи масивів об'єктів. Даний метод порівнює об'єкт, що викликається з obj. На відміну від методу equals, який повертає true або false , compareToповертає:
  • 0 якщо значення рівні;
  • Негативне значення, якщо об'єкт, що викликається, менший за параметр;
  • Позитивне значення , якщо об'єкт, що викликається, більший за параметр.
Насамперед він зручний для сортування впорядкованих списків ( java.util.List) та масивів об'єктів. Якщо список/масив містить елементи, що реалізують цей інтерфейс, вони можуть бути відсортовані автоматично методами java.util.Collections.sort(List)/Arrays.sort(Object[]). З інтерфейсом Comparableпов'язане поняття натурального впорядкування, оскільки він встановлює натуральний порядок екземплярів будь-якого класу, що реалізує цей інтерфейс. Інакше висловлюючись, порядок (x, y) відповідає виконанню умови x.compareTo(y) <= 0. Правила реалізації Comparable, а вірніше, його методу compareTo(Object)такі (x та y – екземпляри класу, що реалізує Comparable):
  • x.compareTo(y)повертає -1 або 1, якщо x повинен знаходитися відповідно раніше або пізніше y. Якщо метод повертає 0, то порядки (x, y) та (y, x) еквівалентні.
  • Якщо sign(a)– функція, що повертає -1,0,1 для а, відповідно, менше 0, що дорівнює 0 і більше 0, то має виконуватись рівність sign(x.compareTo(y))==-sign(y.compareTo(x)). Що логічно: якщо x йде раніше за y, то y повинен йти пізніше x, і навпаки.
  • Якщо x.compareTo(y) > 0і y.compareTo(z) > 0, то x.compareTo(z) > 0співвідношення транзитивності нерівностей.
  • Якщо x.compareTo(y) == 0, то sign(x.compare(z)) == sign(y.compareTo(z))для будь-яких z.
  • Виклик x.compareTo(null)повинен кидати виняток NullPointerException. У цьому є розбіжність із логікою реалізації equals(нагадаю, x.equals(null)повертає false ).
  • Якщо y за своїм типом не може бути порівняний з x, виклик x.compareTo(y)повинен кидати виняток ClassCastException.
  • (x.compareTo(y) == 0) == x.equals(y), тобто. виклик x.compareTo(y)повинен повертати 0 тоді, і тільки тоді, коли x.equals(y)повертає true . Це правило несуперечливості, і його дуже важливо враховувати.
Джерела:

2. Як користуватись інтерфейсом Comparator?

В інтерфейсі Comparatorоголошено два методи compare(Object obj1, Object obj2)та equals(Object obj). При використанні інтерфейсу Comparatorлогіка порівняння пари об'єктів не ховається всередину класу/об'єкта, а реалізується в окремому класі. Метод compare(x,y)точно відповідає за своєю суттю виклику x.compareTo(y). Так само повинні виконуватися всі правила, як і правила реалізації методу compareTo(Object)інтерфейсу Comparable. Comparatorможе використовуватися в будь-якому місці, де потрібне сортування. При цьому, по-перше, з'являється необхідна гнучкість – можливість кількох правил сортування. А по-друге, об'єкти, що сортуються, можуть не реалізовувати інтерфейс Comparable. Якщо вони його все-таки реалізують, Comparatorмає пріоритет. Інтерфейс Comparatorвизначає ще й метод equals(Object), хоч як це парадоксально. Цей метод служить для порівняння самих екземплярів інтерфейсу Comparatorі повинен повертати true тільки в тому випадку, якщо об'єкти, що порівнюються, забезпечують однаковий порядок сортування. Однак завжди безпечно залишати вихідну реалізацію Object.equals(Object)недоторканою .

3. Які методи мають клас Collections?

public static <T> boolean addAll(Collection<? super T> c, T... elements) Метод додає елементи масиву elementsдо колекції Collection<? super T> c. Елементи можуть бути вказані поодинці або як масив. Коли елементи вказані окремо, цей метод надає можливість зручно додати всі елементи до наявної колекції: 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) Обидва методи шукають у списку переданому в параметрі об'єкт, переданий у параметрі, використовуючи алгоритм двійкового пошуку. Повертають індекс елемента, якщо такий елемент у списку є, інакше індекс першого елемента списку більшого key, якщо всі елементи менші key, повертає list.size(). Перед використанням цих методів списки мають бути відсортовані. У першому випадку відсортовані за зростанням у "природному" порядку прямування елементів списку (такий самий, як при використанні Collections.sort(list)). У другому випадку список повинен бути відсортований за зростанням у порядку слідування, який забезпечує переданий компаратор (такий самий порядок, як при використанні Collections.sort(list, c)[тут "с" - компаратор з параметрів методу, що описується)) public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) Преамбула: механізм дженериків у мові забезпечує перевірку типів під час компіляції . Зазвичай цього й достатньо, проте трапляються випадки, коли таки немає. Наприклад, ми нашу колекцію передаємо в код бібліотеки, кудись набік, нам невідому, і нам дуже хочеться, щоб код цієї "third-party library" не вставив у нашу колекцію елемент неправильного типу. Це ось можлива проблема №1. Можлива проблема №2 наступна. Припустимо наша програма видає нам ClassCastException , який повідомляє нам про те, що в колекцію був вставлений елемент неправильного типу. На жаль, цей виняток може вилетіти в будь-який момент, після того, як неправильний елемент був вставлений, і зазвичай надає нам зовсім небагато або взагалі нуль інформації про джерело проблеми. Використовуючи метод метод checkedCollectionми можемо позбавити себе проблеми один і два, т.к. цей метод створює колекцію, що перевіряється на етапі виконання. Вирішення проблеми номер два, за допомогою цього методу: Наприклад ми маємо ось це, і у нас вивалюється ClassCastException.
Collection<String> c = new HashSet<String>();
Код вище можна тимчасово замінити на:
Collection<String> c = Collections.checkedCollection(
         new HashSet<String>(), String.class);
При запуску програми ми знову локалізуємо рядок коду, який вставляє елемент неправильного типу в нашу колекцію. Споріднені на мій погляд методи: 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) Метод копіює елементи src у dest. індекси у копійованих елементів збігатимуться. 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) Способи повертають мінімальний\максимальний елемент у колекції з погляду "природного порядку"(інтерфейс Comparable) або порядку переданого компаратора. public static boolean disjoint(Collection<?> c1,Collection<?> c2) Повертає true якщо колекції не мають однакових елементів. <T> List <T> emptyList(), <K,V> Map <K,V> emptyMap(), <T> Set <T> emptySet()– повертають порожній список, карту відображення та безліч відповідно; <T> void fill(List<? super T> list, T obj)- Заповнює список заданим елементом; int frequency(Collection<?> c, Object o)– повертає кількість входження до колекції заданого елемента; <T> List <T> nCopies(int n, T o)– повертає список із nзаданих елементів; <T> boolean replaceAll(List<T> list, T oldVal, T newVal)- Замінює всі задані елементи новими; void reverse(List<?> list)- "перевертає" список; void rotate(List<?> list, int distance)- Зсуває список циклічно на задану кількість елементів; void shuffle(List<?> list)- Перетасовує елементи списку; <T> Set <T> singleton(T o), singletonList(T o), singletonMap(K key, V value)- Створюють безліч, список і карту відображення, що складаються з одного елемента; <T extends Comparable<? super T>> void sort(List<T> list), <T> void sort(List<T> list, Comparator<? super T> c)– сортування списку, природним порядком та використовуючи Comparatorвідповідно; void swap(List<?> list, int i, int j)– змінює місцями елементи списку, що стоять на заданих позиціях. Джерела:

4. Які методи є у класу Arrays?

Повний перелік методів класу Arrays можна побачити у документації . У цьому конспекті наведу лише деякі з них. [перекладав методи з документації, і на жаль втратив більшу частину свого перекладу. Прикро, і витрачати час на те саме не хочеться, так що вставлю нагуглене] public static <T> List<T> asList(T... a) формує список на основі масиву. Масив у своїй використовується для внутрішнього уявлення списку. Таким чином зберігається зв'язок між списком та вихідним масивом: зміни в масиві позначаться на списку:
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]
зміни у списку позначаться на масиві:
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]
Якщо масив містить об'єкти, очевидно, і масив і список будуть посилатися на одні й ті самі екземпляри:
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(параметры)– перевантажений метод організації бінарного пошуку значення масивах примітивних і об'єктних типів. Повертає позицію першого збігу; void fill(параметры)– перевантажений метод для заповнення масивів значеннями різних типів та примітивами; void sort(параметри) – перевантажений метод сортування масиву або його частини з використанням інтерфейсу Comparator без нього; static <T> T[] copyOf(T[] original, int newLength)-Заповнює масив певної довжини, відкидаючи елементи або заповнюючи null при необхідності; static <T> T[] copyOfRange(T[] original, int from, int to)- Копіює задану область масиву в новий масив; <T> List<T> asList(T… a)– метод, що копіює елементи масиву об'єкт типу List<T>. Джерело:

5. Як називається сортування, яке використовується під час виклику Collections.sort()?

З документації : Реалізація є адаптованим варіантом сортування списку для Python Тіма Петерса (TimSort). Дана реалізація скидає список масив, сортує масив, потім проходить по списку і перезавантажує кожен елемент списку з відповідного елемента масиву. Це дозволяє уникнути складності n*n log(n), яка виникла б при спробі відсортувати зв'язковий список безпосередньо .: Timsort - гібридний алгоритм сортування, що поєднує сортування вставками та сортування злиттям, опублікований в 2002 році Тімом Петерсом. В даний час Timsort є стандартним алгоритмом сортування у Python, OpenJDK 7 та реалізований в Android JDK 1.5. Основна ідея алгоритму в тому, що в реальному світі масиви даних, що сортуються, часто містять у собі впорядковані підмасиви. На таких даних Timsort значно швидше за багато алгоритмів сортування.

10. Що таке ітератор?

Поданий у релізі JDK 1.2 мови Java інтерфейс java.util.Iteratorзабезпечує ітерацію контейнерних класів. Кожен Iterator реалізує методи next()і hasNext()додатково може підтримувати метод remove(). Ітератори створюються відповідними контейнерними класами, зазвичай методом iterator(). Метод next()переводить ітератор на таке значення і повертає значення ітератору. При початковому створенні ітератор вказує на спеціальне значення перед першим елементом, тому перший елемент можна отримати тільки після першого виклику next(). Для визначення моменту, коли всі елементи контейнера були перебрані, використовується тестовий метод hasNext(). Наступний приклад демонструє просте використання ітераторів:
Iterator iter = list.iterator();
//Iterator<MyType> iter = list.iterator(); в J2SE 5.0
while (iter.hasNext())
    System.out.println(iter.next());
Для колекції типів, що підтримує подібне, метод ітератора remove()видаляє останній "відвіданий" елемент контейнера. Багато інших типів модифікації контейнера під час ітерації є небезпечними. Крім того, java.util.Listіснує java.util.ListIteratorз подібним API, але що дозволяє пряму і зворотну ітерації, забезпечуючи визначення поточного індексу в списку і перехід до елемента за його позицією. Джерело: Частина 2
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ