Skip to content

Latest commit

 

History

History
115 lines (82 loc) · 17.7 KB

collections.md

File metadata and controls

115 lines (82 loc) · 17.7 KB

Оглавление

Collection Framework

Вопросы про методы Equals, hashcode и их связь с HashMap.

Контракт. Далее разговор переходит к устройству HashMap. Как устроена внутри? А происходит в случае возникновения коллизии? Назовите алгоритмические сложности поиска, чтения, удаления из элемента мапы. А что если ключ - это массив байтов? А может быть так, что мы положим элемент в мапу, а потом не найдем? Обсасывают бедную мапу со всех сторон. Самая популярная тема для обсуждения.

Контракт equals и hashcode:

  1. Для одного и того же объекта хэшкоды одинаковые.
  2. Если объекты равны по equals, то и хэшкоды одинаковые.
  3. Если же хэшкоды равны, то объекты могут быть не равны по equals (коллизия).
  4. Если хэшкоды разные, то и объекты разные.

В статье на Хабре это подробно разобрано, если кому-то покажется мало.

Про HashMap и вопросы по ним есть несколько отличных статей на Хабре (в картинках, с дополнениями из Java 8, а тут вопросы-ответы про коллекциям). Кроме того, можно посмотреть исходный код в вашей любимой IDE. Можете сделать себе конспект и повесить на стену :)

к содержанию

Вопросы про списки: какие есть, алгоритмическая сложность, какой брать для вставки в середину, в конец, в огурец.

По сути это вопрос про ArrayList vs LinkedList. Опять же, заезженная пластинка, разобранная на Хабре - вопросы-ответы про коллекциям, ArrayList в картинках, LinkedList в картинках, Что «под капотом» у LinkedList. Посмотреть исходники тоже полезно. Например, можно понтануться тем, что вставка в середину в ArrayList выполняется с помощью нативно реализованной функции System.arraycopy, поэтому не всё так плохо, как могло бы быть в этом случае.

к содержанию

Перечислите методы класса Object.

Этот вопрос далее перетекает либо в обсуждение HashMap, либо в основы многопоточного программирования на Java.

Чтобы вы вдруг внезапно не забыли каких-то методов (как это сделал я :D), привожу вам список и ссылку на JavaDoc:

  • clone
  • equals
  • finalize (Deprecated)
  • getClass
  • hashCode
  • toString
  • notify
  • notifyAll
  • wait

Также можно почитать, что там вообще есть в исходниках Object в статье на Хабре.

к содержанию

Что можно положить и достать из List<? extends Number>, а что с List<? super Number>? Что такое ковариантность, контрвариантность, инвариантность?

Тут речь пойдёт про PECS - Producer extends, Consumer super (Joshua Bloch, Effective Java). А также вариантность — перенос наследования исходных типов на производные от них типы (контейнеры, делегаты, обобщения).

Ковариантность (covariance) - перенос наследования исходных типов на производные от них типы в прямом порядке. Переменной типа List<? extends T> разрешено присвоить экземпляр списка, параметризованного T или его подклассом, но не родительским классом. В список типа List<? extends T> нельзя добавить никакой объект (можно только null) - нельзя гарантировать какого именно типа экземпляр списка будет присвоен переменной, поэтому нельзя гарантировать, что добавляемый объект разрешён в таком списке. Однако, из списка можно прочитать объект и он будет типа T и экземпляром либо T, либо одного из подклассов T. Соответственно, List<? extends Number> можно присвоить ArrayList<Number> или ArrayList<Integer>, но не ArrayList<Object>. Метод get возвращает Number, за которым может скрываться экземпляр Integer или другого наследника Number. Массивы также ковариантны. Переопределение методов, начиная с Java 5, ковариантно относительно типа результата и исключений.

List<?> аналогичен List<? extends Object> со всеми вытекающими.

Контрвариантность (contravariance) - перенос наследования исходных типов на производные от них типы в обратном порядке. Переменной типа List<? super T> разрешено присвоить экземпляр списка, параметризованного T или его родительским классом, но не его подклассом. В список типа List<? super T> можно добавить экземпляр T или его подкласса, но нельзя добавить экземпляр родительских для T классов. Из такого списка с гарантией можно прочитать только Object, за которым может скрываться неизвестно какой его подкласс.

Соответственно, List<? super Number> можно присвоить либо ArrayList<Number>, либо ArrayList<Object>, но не список наследников Number(т.е. никаких ArrayList<Integer>). Можно добавить экземпляр Integer или Double (можно было бы Number, но он абстрактный), но нельзя - Object. Метод get возвращает Object - точнее сказать нельзя.

Инвариантность - наследование исходных типов не переносится на производные. Переменной типа List разрешено присвоить экземпляр списка, параметризованного только T. В список можно добавить экземпляр T или его подкласса. Список возвращает T, за которым может скрываться экземпляр его подкласса.

Соответственно, List<Number> можно присвоить ArrayList<Number>, но не ArrayList<Integer> или ArrayList<Object>. Можно добавить экземпляр Integer или Double (можно было бы Number, но он абстрактный), но нельзя - Object. Метод get возвращает Number, за которым может скрываться экземпляр Integer или другого наследника Number.

Подробнее:

к содержанию

Что внутри и как работают TreeSet/TreeMap? В чем идея Красно-черного дерева?

TreeMap - реализация NavigableMap, основанная на красно-чёрном дереве. Элементы отсортированы по ключам в натуральном порядке или с помощью Comparator, указанного при создании мапы, в зависимости от использовавшегося конструктора. Гарантирует логарифмическое время выполнения методов containsKey, get, put и remove. TreeSet - реализация NavigableSet, основанная на TreeMap. Элементы отсортированы в натуральном порядке или с помощью Comparator, указанного при создании множества, в зависимости от использовавшегося конструктора. Гарантирует логарифмическое время выполнения методов add, contains и remove.

Обе коллекции НЕ synchronized и итератор по ним может выбросить ConcurrentModificationException.

Если в эти коллекции при использовании натурального порядка сортировки в качестве ключа попытаться положить null, то получим NullPointerException. В случае с компаратором поведение с null будет зависеть от реализации компаратора. До 7-й Java с добавлением null в TreeMap и TreeSet был баг.

Самая важная особенность красно-чёрного дерева в том, что оно умеет само себя балансировать, поэтому не важно в каком порядке будут добавляться в него элементы, преимущества этой структуры данных будут сохраняться. Сбалансированность достигается за счёт поддержания правил красно-чёрной раскраски вершин:

  • Вершина может быть либо красной, либо чёрной и имеет двух потомков
  • Красная вершина не может быть дочерней для красной вершины
  • Количество чёрных вершин от корня до листа включительно одинаково для любого листа
  • Корень дерева является чёрным
  • Все листья — чёрные и не содержат данных

Подробнее:

к содержанию