Складні та цікаві питання на співбесіді з Java про колекції

Колекції в Java є основою мови, вони забезпечують роботу таких структур, як прості списки і складні багатозадачні дані. Якщо ви готуєтесь до співбесіди з Java, питання про колекції майже гарантовані. Тут я розгляну дев'ять складних та цікавих питань на цю тему, а також надам практичні приклади коду, щоб допомогти вам успішно пройти співбесіду.

1. Як HashMap обробляє колізії всередині?

Чому це запитують: Розуміння того, як обробляються колізії, важливе для розуміння ефективності роботи HashMap.

Відповідь: HashMap використовує кошики (buckets) для зберігання пар ключ-значення. Один кошик може містити кілька елементів, якщо кілька ключів хешуються в той самий індекс. Спочатку ці елементи зберігаються як зв'язаний список. Якщо кількість елементів у кошику перевищує певний поріг (за замовчуванням 8), список перетворюється на збалансоване дерево для оптимізації часу доступу.

Питання для продовження: Що відбувається, якщо розмір кошика досягає або перевищує поріг?

Відповідь на продовження: Коли розмір кошика досягає порогу (за замовчуванням 0,75 * ємність), HashMap змінює розмір, подвоюючи ємність та перевизначаючи хешування всіх ключів у нові кошики. Це забезпечує, що середня складність операцій get/put залишається O(1).

2. Як реалізувати власний Comparator для сортування списку об'єктів за кількома полями?

Чому це запитують: Показує розуміння ланцюжків Comparator.

Приклад коду:

import java.util.*;  
class Employee {  
 String name;  
 int age;  
 double salary;  
 Employee(String name, int age, double salary) {  
 this.name = name;  
 this.age = age;  
 this.salary = salary;  
 }  
 @Override  
 public String toString() {  
 return name + " (Age: " + age + ", Salary: " + salary + ")";  
 }  
}  
public class ComparatorChainingExample {  
 public static void main(String[] args) {  
 List employees = Arrays.asList(  
 new Employee("Alice", 30, 70000),  
 new Employee("Bob", 25, 50000),  
 new Employee("Charlie", 30, 80000)  
 );  
 employees.sort(Comparator  
 .comparing((Employee e) -> e.age)  
 .thenComparing((Employee e) -> e.salary, Comparator.reverseOrder()));  
 System.out.println("Sorted Employees: " + employees);  
 }  
}

3. Як виявити та обробити ConcurrentModificationException в багатозадачному середовищі?

Чому це запитують: Перевіряє розуміння безпеки потоків у колекціях.

Приклад коду:

import java.util.ArrayList;  
import java.util.Iterator;  
public class ConcurrentModificationExample {  
 public static void main(String[] args) {  
 ArrayList list = new ArrayList<>();  
 list.add(1);  
 list.add(2);  
 Thread thread1 = new Thread(() -> {  
 Iterator iterator = list.iterator();  
 while (iterator.hasNext()) {  
 System.out.println(iterator.next());  
 list.add(3); // Це викличе ConcurrentModificationException  
 }  
 });  
 Thread thread2 = new Thread(() -> list.add(4));  
 thread1.start();  
 thread2.start();  
 }  
}

Рішення: Використовуйте колекції для багатозадачності, такі як CopyOnWriteArrayList.

Приклад рішення:

import java.util.concurrent.CopyOnWriteArrayList;  
public class ConcurrentCollectionExample {  
 public static void main(String[] args) {  
 CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();  
 list.add(1);  
 list.add(2);  
 Thread thread1 = new Thread(() -> {  
 for (Integer i : list) {  
 System.out.println(i);  
 list.add(3); // Тут не буде виключення  
 }  
 });  
 Thread thread2 = new Thread(() -> list.add(4));  
 thread1.start();  
 thread2.start();  
 }  
}

4. У чому різниця між IdentityHashMap та HashMap?

Чому це запитують: Перевіряє глибоке розуміння хеш-таблиць.

Відповідь: IdentityHashMap використовує порівняння за посиланням (==) для ключів, тоді як HashMap використовує метод equals() для порівняння.

5.

5. Як TreeMap обробляє нульові ключі та значення?

Чому це запитують: Показує особливості поведінки TreeMap.

Відповідь:

  • TreeMap не дозволяє використовувати нульові ключі.
  • Він дозволяє мати кілька нульових значень.

Приклад коду:

import java.util.TreeMap;  
public class TreeMapNullKeyExample {  
 public static void main(String[] args) {  
 TreeMap map = new TreeMap<>();  
 map.put("A", null);  
 map.put("B", null);  
 System.out.println("TreeMap: " + map);  
 }  
}

6. Як LinkedHashMap зберігає порядок вставки? Чи можна перевизначити цю поведінку?

Чому це запитують: Перевіряє практичне розуміння роботи LinkedHashMap.

Відповідь: LinkedHashMap використовує двозв'язний список для збереження порядку вставки. За допомогою параметра accessOrder, встановленого в true в конструкторі, можна змінити порядок на основі доступу.

Приклад коду:

import java.util.LinkedHashMap;  
public class LinkedHashMapExample {  
 public static void main(String[] args) {  
 LinkedHashMap map = new LinkedHashMap<>(16, 0.75f, true);  
 map.put("A", 1);  
 map.put("B", 2);  
 map.put("C", 3);  
 map.get("A"); // Доступ до "A"  
 System.out.println("LinkedHashMap: " + map);  
 }  
}

7. Що відбувається, коли ви намагаєтесь змінити колекцію під час ітерації?

Чому це запитують: Охоплює поведінку fail-fast.

Відповідь: Ви отримаєте ConcurrentModificationException, якщо колекція буде змінена структурно (наприклад, додавання або видалення елементів) під час ітерації за допомогою не-конкурентної колекції.

Рішення: Використовуйте Iterator.remove() для безпечного видалення.

Приклад коду:

import java.util.ArrayList;  
import java.util.Iterator;  
public class FailFastExample {  
 public static void main(String[] args) {  
 ArrayList list = new ArrayList<>();  
 list.add("A");  
 list.add("B");  
 Iterator iterator = list.iterator();  
 while (iterator.hasNext()) {  
 iterator.next();  
 iterator.remove(); // Безпечне видалення  
 }  
 System.out.println("Modified List: " + list);  
 }  
}

8. Який за замовчуванням коефіцієнт заповнення (load factor) у HashMap, і чому він встановлений на 0.75?

Чому це запитують: Перевіряє розуміння оптимізації продуктивності в HashMap.

Відповідь: Коефіцієнт заповнення 0.75 досягає балансу між часом (повторне хешування) і простором (додаткові кошики).

Питання для продовження: Що відбувається, якщо коефіцієнт заповнення встановити на більше значення?

Відповідь на продовження: Якщо коефіцієнт заповнення більший, HashMap буде рідше змінювати розмір, що зекономить час при вставках, але може призвести до більших часів доступу через більші колізії в кошиках.

9. Як PriorityQueue реалізує свою внутрішню структуру?

Чому це запитують: Перевіряє знання про структури даних на основі купи.

Відповідь: PriorityQueue реалізовано як бінарну купу, де пріоритет визначає порядок купи (за замовчуванням мін-купа).

Приклад коду:

import java.util.PriorityQueue;  
public class PriorityQueueExample {  
 public static void main(String[] args) {  
 PriorityQueue pq = new PriorityQueue<>();  
 pq.add(10);  
 pq.add(5);  
 pq.add(15);  
 while (!pq.isEmpty()) {  
 System.out.println(pq.poll()); // Виводить в відсортованому порядку  
 }  
 }  
}

Оволодіння нюансами фреймворку колекцій Java може допомогти вам виділитись на співбесіді. Розуміння внутрішньої роботи, практичних випадків використання та деталей реалізації дозволить вам не лише відповісти на технічні питання, але й писати ефективний і підтримуваний код. Успіхів у програмуванні та удачі на співбесідах!

Для більше таких статей — https://medium.com/@poojaauma

Перекладено з: Tricky and Interesting Java Interview Questions on Collections

Leave a Reply

Your email address will not be published. Required fields are marked *