Oc-windows.ru

IT Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java found set required collection

Множества: Set, HashSet, LinkedHashSet, TreeSet

HashSet, TreeSet и LinkedHashSet относятся к семейству Set. В множествах Set каждый элемент хранится только в одном экземпляре, а разные реализации Set используют разный порядок хранения элементов. В HashSet порядок элементов определяется по сложному алгоритму. Если порядок хранения для вас важен, используйте контейнер TreeSet, в котором объекты хранятся отсортированными по возрастанию в порядке сравнения или LinkedHashSet с хранением элементов в порядке добавления.

Множества часто используются для проверки принадлежности, чтобы вы могли легко проверить, принадлежит ли объект заданному множеству, поэтому на практике обычно выбирается реализация HashSet, оптимизированная для быстрого поиска.

В Android 11 (R) обещают добавить несколько перегруженных версий метода of(), которые являются частью Java 8.

HashSet

Название Hash. происходит от понятия хэш-функция. Хэш-функция — это функция, сужающая множество значений объекта до некоторого подмножества целых чисел. Класс Object имеет метод hashCode(), который используется классом HashSet для эффективного размещения объектов, заносимых в коллекцию. В классах объектов, заносимых в HashSet, этот метод должен быть переопределен (override).

Имеет два основных конструктора (аналогично ArrayList):

Методы

  • public Iterator iterator()
  • public int size()
  • public boolean isEmpty()
  • public boolean contains(Object o)
  • public boolean add(Object o)
  • public boolean addAll(Collection c)
  • public Object[] toArray()
  • public boolean remove(Object o)
  • public boolean removeAll(Collection c)
  • public boolean retainAll(Collection c) — (retain — сохранить). Выполняет операцию «пересечение множеств».
  • public void clear()
  • public Object clone()

Методы аналогичны методам ArrayList за исключением того, что метод add(Object o) добавляет объект в множество только в том случае, если его там нет. Возвращаемое методом значение — true, если объект добавлен, и false, если нет.

Перейдём к практике. Как это ни странно, но в жизни встречаются несколько Барсиков, Мурзиков и прочих Рыжиков. Несмотря на одинаковые имена, каждый кот неповторим. Надеюсь, с этим никто не спорит. Но пихать имена котов в множество HashSet не стоит, так как в множестве может храниться только одно имя и двух Мурзиков тут не записать. Другое дело — страны. Не может быть двух Франций, двух Англий, двух Россий (даже партия такая есть Единая Россия, впрочем мы отвлеклись).

Итак, создадим множество стран.

Нажав на кнопку, вы получите результат Размер HashSet = 4.

Даже если вы попытаетесь схитрить и дополнительно вставить строку countryHashSet.add(«Кот-Д’Ивуар»); после России, то всё-равно размер останется прежним.

Убедиться в этом можно, если вызвать метод iterator(), который позволяет получить всё множество элементов:

Несмотря на наше упрямство, мы видим только четыре добавленных элемента.

Стоит отметить, что порядок добавления стран во множество будет непредсказуемым. HashSet использует хэширование для ускорения выборки. Если вам нужно, чтобы результат был отсортирован, то пользуйтесь TreeSet.

Преобразовать в массив и вывести в ListView

Следующий пример — задел на будущее. Когда вы узнаете, что такое ListView, то вернитесь к этому уроку и узнайте, как сконвертировать множество в массив и вывести результат в компонент ListView (Список):

Продолжим опыты. Поработаем теперь с числами.

Здесь мы ещё раз убеждаемся, что повторное добавление числа не происходит. В цикле случайным образом выбирается число от 0 до 9 тысячу раз. Естественно, многие числа должны были повториться при таком сценарии, но во множество каждое число попадёт один раз.

При этом данные не сортируются, так как расположены как попало.

Специально для Android был разработан новый класс ArraySet, который более эффективен.

LinkedHashSet

Класс LinkedHashSet расширяет класс HashSet, не добавляя никаких новых методов. Класс поддерживает связный список элементов набора в том порядке, в котором они вставлялись. Это позволяет организовать упорядоченную итерацию вставки в набор.

TreeSet

Переделанный пример для вывода случайных чисел в отсортированном порядке. HashSet не может гарантировать, что данные будут отсортированы, так как работает по другому алгоритму. Если сортировка для вас важна, то используйте TreeSet.

Со строками это выглядит нагляднее:

Названия стран выведутся в алфавитном порядке.

Класс TreeSet создаёт коллекцию, которая для хранения элементов применяет дерево. Объекты сохраняются в отсортированном порядке по возрастанию.

SortedSet

В примере с TreeSet использовался интерфейс SortedSet, который позволяет сортировать элементы множества. По умолчанию сортировка производится привычным способом, но можно изменить это поведение через интерфейс Comparable.

Кроме стандартных методов Set у интерфейса есть свои методы.

  • Comparator comparator()
  • subSet(Object fromElement, Object toElement)
  • tailSet(Object fromElement)
  • headSet(Object toElement)
  • Object first()
  • Object last()

Справочник по Java Collections Framework

Данная публикация не является полным разбором или анализом (не покрывает пакет java.util.concurrent ). Это, скорее, справочник, который поможет начинающим разработчикам понять ключевые отличия одних коллекций от других, а более опытным разработчикам просто освежить материал в памяти.

Читать еще:  Java util timer

Что такое Java Collections Framework?

Java Collection Framework — иерархия интерфейсов и их реализаций, которая является частью JDK и позволяет разработчику пользоваться большим количесвом структур данных из «коробки».

Базовые понятия

На вершине иерархии в Java Collection Framework располагаются 2 интерфейса: Collection и Map . Эти интерфейсы разделяют все коллекции, входящие во фреймворк на две части по типу хранения данных: простые последовательные наборы элементов и наборы пар «ключ — значение» (словари).

Collection — этот интерфейс находится в составе JDK c версии 1.2 и определяет основные методы работы с простыми наборами элементов, которые будут общими для всех его реализаций (например size() , isEmpty() , add(E e) и др.). Интерфейс был слегка доработан с приходом дженериков в Java 1.5. Так же в версии Java 8 было добавлено несколько новых метода для работы с лямбдами (такие как stream() , parallelStream() , removeIf(Predicate filter) и др.).

Важно также отметить, что эти медоды были реализованы непосредственно в интерфейсе как default -медоды.

Map. Данный интерфейс также находится в составе JDK c версии 1.2 и предоставляет разработчику базовые методы для работы с данными вида «ключ — значение».Также как и Collection , он был дополнен дженериками в версии Java 1.5 и в версии Java 8 появились дополнительные методы для работы с лямбдами, а также методы, которые зачастую реализовались в логике приложения ( getOrDefault(Object key, V defaultValue) , putIfAbsent(K key, V value) ).

Интерфейс Map [doc]

Hashtable — реализация такой структуры данных, как хэш-таблица. Она не позволяет использовать null в качестве значения или ключа. Эта коллекция была реализована раньше, чем Java Collection Framework, но в последствии была включена в его состав. Как и другие коллекции из Java 1.0, Hashtable является синхронизированной (почти все методы помечены как synchronized ). Из-за этой особенности у неё имеются существенные проблемы с производительностью и, начиная с Java 1.2, в большинстве случаев рекомендуется использовать другие реализации интерфейса Map ввиду отсутствия у них синхронизации.

HashMap — коллекция является альтернативой Hashtable . Двумя основными отличиями от Hashtable являются то, что HashMap не синхронизирована и HashMap позволяет использовать null как в качестве ключа, так и значения. Так же как и Hashtable , данная коллекция не является упорядоченной: порядок хранения элементов зависит от хэш-функции. Добавление элемента выполняется за константное время O(1), но время удаления, получения зависит от распределения хэш-функции. В идеале является константным, но может быть и линейным O(n). Более подробную информацию о HashMap можно почитать здесь (актуально для Java HashMap , порядок итерирования равен порядку добавления элементов. Данная особенность достигается благодаря двунаправленным связям между элементами (аналогично LinkedList ). Но это преимущество имеет также и недостаток — увеличение памяти, которое занимет коллекция. Более подробная информация изложена в этой статье.

TreeMap — реализация Map основанная на красно-чёрных деревьях. Как и LinkedHashMap является упорядоченной. По-умолчанию, коллекция сортируется по ключам с использованием принципа «natural ordering», но это поведение может быть настроено под конкретную задачу при помощи объекта Comparator , которые указывается в качестве параметра при создании объекта TreeMap .

WeakHashMap — реализация хэш-таблицы, которая организована с использованием weak references. Другими словами, Garbage Collector автоматически удалит элемент из коллекции при следующей сборке мусора, если на ключ этого элеметна нет жёстких ссылок.

Интерфейс List [doc]

Реализации этого интерфейса представляют собой упорядоченные коллекции. Кроме того, разработчику предоставляется возможность доступа к элементам коллекции по индексу и по значению (так как реализации позволяют хранить дубликаты, результатом поиска по значению будет первое найденное вхождение).

Vector — реализация динамического массива объектов. Позволяет хранить любые данные, включая null в качестве элемента. Vector появился в JDK версии Java 1.0, но как и Hashtable , эту коллекцию не рекомендуется использовать, если не требуется достижения потокобезопасности. Потому как в Vector , в отличии от других реализаций List , все операции с данными являются синхронизированными. В качестве альтернативы часто применяется аналог — ArrayList .

Stack — данная коллекция является расширением коллекции Vector . Была добавлена в Java 1.0 как реализация стека LIFO (last-in-first-out). Является частично синхронизированной коллекцией (кроме метода добавления push() ). После добавления в Java 1.6 интерфейса Deque , рекомендуется использовать именно реализации этого интерфейса, например ArrayDeque .

ArrayList — как и Vector является реализацией динамического массива объектов. Позволяет хранить любые данные, включая null в качестве элемента. Как можно догадаться из названия, его реализация основана на обычном массиве. Данную реализацию следует применять, если в процессе работы с коллекцией предплагается частое обращение к элементам по индексу. Из-за особенностей реализации поиндексное обращение к элементам выполняется за константное время O(1). Но данную коллекцию рекомендуется избегать, если требуется частое удаление/добавление элементов в середину коллекции. Подробный анализ и описание можно почитать в этом хабратопике.

Читать еще:  Java для web разработки

LinkedList — ещё одина реализация List . Позволяет хранить любые данные, включая null . Особенностью реализации данной коллекции является то, что в её основе лежит двунаправленный связный список (каждый элемент имеет ссылку на предыдущий и следующий). Благодаря этому, добавление и удаление из середины, доступ по индексу, значению происходит за линейное время O(n), а из начала и конца за константное O(1). Так же, ввиду реализации, данную коллекцию можно использовать как стек или очередь. Для этого в ней реализованы соответсвующие методы. На Хабре также есть статья с подробным анализом и описанием этой коллекции.

Интерфейс Set [doc]

Представляет собой неупорядоченную коллекцию, которая не может содержать дублирующиеся данные. Является программной моделью математического понятия «множество».

HashSet — реализация интерфейса Set , базирующаяся на HashMap . Внутри использует объект HashMap для хранения данных. В качестве ключа используется добавляемый элемент, а в качестве значения — объект-пустышка (new Object()). Из-за особенностей реализации порядок элементов не гарантируется при добавлении.

LinkedHashSet — отличается от HashSet только тем, что в основе лежит LinkedHashMap вместо HashSet . Благодаря этому отличию порядок элементов при обходе коллекции является идентичным порядку добавления элементов.

TreeSet — аналогично другим классам-реализациям интерфейса Set содержит в себе объект NavigableMap , что и обуславливает его поведение. Предоставляет возможность управлять порядком элементов в коллекции при помощи объекта Comparator , либо сохраняет элементы с использованием «natural ordering».

Интерфейс Queue [doc]

Этот интерфейс описывает коллекции с предопределённым способом вставки и извлечения элементов, а именно — очереди FIFO (first-in-first-out). Помимо методов, определённых в интерфейсе Collection, определяет дополнительные методы для извлечения и добавления элементов в очередь. Большинство реализаций данного интерфейса находится в пакете java.util.concurrent и подробно рассматриваются в данном обзоре.

PriorityQueue — является единственной прямой реализацией интерфейса Queue (была добавлена, как и интерфейс Queue, в Java 1.5), не считая класса LinkedList , который так же реализует этот интерфейс, но был реализован намного раньше. Особенностью данной очереди является возможность управления порядком элементов. По-умолчанию, элементы сортируются с использованием «natural ordering», но это поведение может быть переопределено при помощи объекта Comparator , который задаётся при создании очереди. Данная коллекция не поддерживает null в качестве элементов.

ArrayDeque — реализация интерфейса Deque, который расширяет интерфейс Queue методами, позволяющими реализовать конструкцию вида LIFO (last-in-first-out). Интерфейс Deque и реализация ArrayDeque были добавлены в Java 1.6. Эта коллекция представляет собой реализацию с использованием массивов, подобно ArrayList , но не позволяет обращаться к элементам по индексу и хранение null . Как заявлено в документации, коллекция работает быстрее чем Stack , если используется как LIFO коллекция, а также быстрее чем LinkedList, если используется как FIFO.

Заключение

Java Collections Framework содержит большое количество различных структур данных, доступных в JDK «из коробки», которые в большинстве случаев покрывают все потребности при реализации логики приложения. Сравнение временных характеристик основных коллекций, которые зачастую используются в разработке приложений приведено в таблице:

При необходимости, разработчик может создать собственную реализацию, расширив или переопределив существующую логику, либо создав свою собственную реализацию подходящего интерфейса с нуля. Также существует некоторое количество готовых решений, которые являются альтернативой или дополнением к Java Collections Framework. Наиболее популярными являются Google Guava и Commons Collections.

Set в Java. Hashset пример

Привет! В нашем самоучителе мы рассмотрим следующие коллекции:

  • Список (List) — см. статью «List в Java», а также «Что такое ArrayList»
  • Множество (Set)
  • Очередь (Queue) — см. статью «Queue в Java»

Это статья про структуру данных множество (Set) — один из способов хранения данных в Java.

Что такое множество (Set)

Как мы уже говорили, множество — это такой же способ хранения данных, как массив или список. Но особенность множества в том, что оно может хранить только уникальные значения.

Например, если у нас есть множество Integer-ов — в нем лежат числа 1, 2 , 3, 4 и 5:

Если мы попробуем добавить туда единицу, у нас не получится — потому что в множестве уже есть единица:

Таким образом, множество обеспечивает уникальность своих элементов. Можете быть спокойны — дублироваться в множествах ничего не будет.

Какие есть виды множеств

Как и List, множество — это всего лишь интерфейс. Давайте посмотрим, какие реализации существуют в Java.

Читать еще:  Не печатает принтер пишет ошибка печати

Как видите, есть три основные виды множеств — HashSet, LinkedHashSet и TreeSet. Есть и другие — но пока мы только знакомимся с Set-ми, пока нам знать нам их совсем не обязательно

Среди HashSet, LinkedHashSet и TreeSet чаще всего используется HashSet.

Чем отличаются HashSet, LinkedHashSet и TreeSet

  • HashSet хранит элементы в произвольном порядке, но зато быстро ищет. Подходит, если порядок Вам не важен, но важна скорость. Более того, для оптимизации поиска, HashSet будет хранить элементы так, как ему удобно.
  • LinkedHashSet будет хранить элементы в порядке добавления, но зато работает медленнее.
  • TreeSet хранит элементы отсортированными.

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

Набор данных интерфейса Set

Реализация интерфейса Set представляет собой неупорядоченную коллекцию, которая не может содержать дублирующие данные.

Интерфейс Set включает следующие методы :

МетодОписание
add(Object o)Добавление элемента в коллекцию, если он отсутствует. Возвращает true, если элемент добавлен.
addAll(Collection c)Добавление элементов коллекции, если они отсутствуют.
clear()Очистка коллекции.
contains(Object o)Проверка присутствия элемента в наборе. Возвращает true, если элемент найден.
containsAll(Collection c)Проверка присутсвия коллекции в наборе. Возвращает true, если все элементы содержатся в наборе.
equals(Object o)Проверка на равенство.
hashCode()Получение hashCode набора.
isEmpty()Проверка наличия элементов. Возвращает true если в коллекции нет ни одного элемента.
iterator()Функция получения итератора коллекции.
remove(Object o)Удаление элемента из набора.
removeAll(Collection c)Удаление из набора всех элементов переданной коллекции.
retainAll(Collection c)Удаление элементов, не принадлежащих переданной коллекции.
size()Количество элементов коллекции
toArray()Преобразование набора в массив элементов.
toArray(T[] a)Преобразование набора в массив элементов. В отличии от предыдущего метода, который возвращает массив объектов типа Object, данный метод возвращает массив объектов типа, переданного в параметре.

К семейству интерфейса Set относятся HashSet, TreeSet и LinkedHashSet. В множествах Set разные реализации используют разный порядок хранения элементов. В HashSet порядок элементов оптимизирован для быстрого поиска. В контейнере TreeSet объекты хранятся отсортированными по возрастанию. LinkedHashSet хранит элементы в порядке добавления.

Набор данных HashSet

Конструкторы HashSet :

Методы HashSet

  • public int size()
  • public boolean isEmpty()
  • public boolean add(Object o)
  • public boolean addAll(Collection c)
  • public boolean remove(Object o)
  • public boolean removeAll(Collection c)
  • public boolean contains(Object o)
  • public void clear()
  • public Object clone()
  • public Iterator iterator()
  • public Object[] toArray()
  • public boolean retainAll(Collection c)

HashSet содержит методы аналогично ArrayList. Исключением является метод add(Object o), который добавляет объект только в том случае, если он отсутствует. Если объект добавлен, то метод add возвращает значение — true, в противном случае false.

Пример использования HashSet :

В консоли мы должны увидеть только 4 записи. Следует отметить, что порядок добавления записей в набор будет непредсказуемым. HashSet использует хэширование для ускорения выборки.

Пример использования HashSet с целочисленными значениями. В набор добавляем значения от 0 до 9 из 25 возможных случайным образом выбранных значений — дублирование не будет.

Следует отметить, что реализация HashSet не синхронизируется. Если многократные потоки получают доступ к набору хеша одновременно, а один или несколько потоков должны изменять набор, то он должен быть синхронизирован внешне. Это лучше всего выполнить во время создания, чтобы предотвратить случайный несинхронизируемый доступ к набору :

Набор данных LinkedHashSet

Класс LinkedHashSet наследует HashSet, не добавляя никаких новых методов, и поддерживает связный список элементов набора в том порядке, в котором они вставлялись. Это позволяет организовать упорядоченную итерацию вставки в набор.

Также, как и HashSet, LinkedHashSet не синхронизируется. Поэтому при использовании данной реализации в приложении с множеством потоков, часть из которых может вносить изменения в набор, следует на этапе создания выполнить синхронизацию :

Набор данных TreeSet

Класс TreeSet создаёт коллекцию, которая для хранения элементов использует дерево. Объекты хранятся в отсортированном порядке по возрастанию.

Конструкторы TreeSet :

Методы TreeSet

  • boolean add(Object o)
  • boolean addAll(Collection c)
  • Object ceiling(Object o)
  • void clear()
  • TreeSet clone()
  • Comparator comparator()
  • boolean contains(Object o)
  • Iterator descendingIterator()
  • NavigableSet descendingSet()
  • Object first()
  • Object floor(Object o)
  • SortedSet headSet(E e)
  • NavigableSet headSet(E e, boolean inclusive)
  • Object higher(Object o)
  • boolean isEmpty()
  • Iterator iterator()
  • E last()
  • E lower(E e)
  • E pollFirst()
  • E pollLast()
  • boolean remove(Object o)
  • int size()
  • Spliterator spliterator()
  • NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
  • SortedSet subSet(E fromElement, E toElement)
  • SortedSet tailSet(E fromElement)
  • NavigableSet tailSet(E fromElement, boolean inclusive)

В следующем измененном примере с использования TreeSet в консоль будут выведены значения в упорядоченном виде.

Ссылка на основную публикацию
Adblock
detector