Ответ 1
Вам нужен Java HashSet.
Описание из официальной документации:
Этот класс реализует интерфейс Set, поддерживаемый хеш-таблицей (фактически, экземпляром HashMap). Это не дает никаких гарантий относительно порядка итераций множества; в частности, это не гарантирует, что порядок останется постоянным с течением времени. Этот класс допускает нулевой элемент.
Этот класс обеспечивает постоянную производительность по времени для основных операций (добавление, удаление, содержание и размер), предполагая, что хеш-функция правильно распределяет элементы между сегментами. Итерации по этому набору требуют времени, пропорционального сумме размера экземпляра HashSet (количество элементов) плюс "емкость" резервного экземпляра HashMap (количество сегментов). Таким образом, очень важно не устанавливать слишком высокую начальную емкость (или слишком низкий коэффициент загрузки), если важна производительность итерации.
Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков обращаются к хэш-набору одновременно, и хотя бы один из потоков изменяет набор, он должен быть синхронизирован извне. Обычно это достигается путем синхронизации с некоторым объектом, который естественным образом инкапсулирует набор. Если такого объекта не существует, набор следует "обернуть" с помощью метода Collections.synchronizedSet. Это лучше всего делать во время создания, чтобы предотвратить случайный несинхронизированный доступ к набору:
Set s = Collections.synchronizedSet(new HashSet (...));
Итераторы, возвращаемые этим методом класса итератора, работают без сбоев: если набор изменяется в любое время после создания итератора, любым способом, кроме как через собственный метод удаления итератора, итератор генерирует исключение ConcurrentModificationException. Таким образом, перед одновременной модификацией итератор быстро и чисто дает сбой, вместо того, чтобы рисковать произвольным недетерминированным поведением в неопределенное время в будущем.
Обратите внимание, что отказоустойчивое поведение итератора не может быть гарантировано, так как, вообще говоря, невозможно сделать какие-либо жесткие гарантии при наличии несинхронизированной параллельной модификации. Отказоустойчивые итераторы создают исключительную ситуацию ConcurrentModificationException. Следовательно, было бы неправильно писать программу, которая зависела от этого исключения в отношении его корректности: поведение итераторов, обеспечивающее отказоустойчивость, следует использовать только для обнаружения ошибок.
Этот класс является членом Java Collections Framework.