Как осуществляется доступ к элементам в List и Set в Java?
Что проверяют
Понимаете ли вы, что у множества нет индексов, и знаете ли стоимость операций поиска в обеих структурах.
Как отвечать
List упорядочен и адресуется индексом: get(i) у ArrayList работает за константу, потому что внутри массив. У LinkedList тот же вызов линейный, потому что приходится идти по ссылкам.
Set индексов не имеет вовсе. Обратиться к «третьему элементу» нельзя, есть только проверка вхождения и обход. У HashSet проверка вхождения в среднем за константу, у TreeSet логарифмическая, зато элементы упорядочены.
Ключевое сравнение, ради которого вопрос и задают:
- поиск значения: у списка это линейный перебор с вызовом
equalsна каждом элементе, у хеш-множества почти мгновенно; - дубликаты: список хранит, множество отбрасывает, и повторное добавление возвращает
false; - порядок обхода: у списка порядок вставки, у
HashSetне гарантирован, уLinkedHashSetпорядок вставки, уTreeSetсортировка; - требования к элементам: множеству нужны корректные
equalsиhashCode, дереву нужна сравнимость.
Как обходят оба: цикл for-each, итератор, потоки. Удаление во время обхода только через итератор или removeIf, иначе исключение о конкурентном изменении.
И практический вывод: если в коде встречается list.contains(...) внутри цикла, это сигнал заменить список на множество и получить линейное время вместо квадратичного.
Где спотыкаются
Пытаются получить элемент множества по индексу и городят преобразование в список на каждой итерации.
Кладут в множество изменяемые объекты и теряют их после изменения полей.
Считают, что HashSet сохраняет порядок, потому что на маленьких наборах он часто выглядит стабильным.