1. Обзор
В этой статье мы рассмотрим Collections , библиотеку Java, предоставляющую постоянные, неизменяемые коллекции.
Постоянные данные структуры (коллекции) не могут быть изменены непосредственно во время операции обновления, вместо этого возвращается новый объект с результатом операции обновления. Они не только неизменяемы, но и постоянны – это означает, что после выполнения модификации предыдущие версии коллекции остаются неизменными.
Коллекции аналогичны и совместимы с платформой Java Collections.
2. Зависимости
Давайте добавим следующую зависимость в ваш pom.xml для нас, чтобы использовать коллекции в нашем проекте:
org.pcollections pcollections 2.1.2
Если наш проект основан на Gradle, мы можем добавить тот же артефакт в наш файл build.gradle :
compile 'org.pcollections:pcollections:2.1.2'
Последнюю версию можно найти на Maven Central .
3. Структура карты (Hashmap)
Hashmap – это постоянная структура данных карты. Это аналог для java.util.HashMap используется для хранения ненулевых данных типа ключ-значение.
Мы можем создать экземпляр Hashmap , используя удобные статические методы в HashTreePMap. Эти статические методы возвращают экземпляр Hashmap , который поддерживается IntTreePMap.
Статический метод empty() класса HashTreePMap создает пустой HashPMap , который не имеет элементов – точно так же, как при использовании конструктора по умолчанию java.util.HashMap :
HashPMappmap = HashTreePMap.empty();
Есть два других статических метода, которые мы можем использовать для создания Hashmap . Метод singleton() создает Hashmap только с одной записью:
HashPMappmap1 = HashTreePMap.singleton("key1", "value1"); assertEquals(pmap1.size(), 1);
Метод from() создает Hashmap из существующего java.util.HashMap экземпляр (и другие java.util.Карта реализации):
Map map = new HashMap(); map.put("mkey1", "mval1"); map.put("mkey2", "mval2"); HashPMappmap2 = HashTreePMap.from(map); assertEquals(pmap2.size(), 2);
Хотя Hashmap наследует некоторые методы из java.util.AbstractMap и java.util.Map , у него есть уникальные для него методы.
Метод минус() удаляет одну запись с карты, в то время как метод минус все() удаляет несколько записей. Есть также методы plus() и plus All () , которые добавляют одну и несколько записей соответственно:
HashPMappmap = HashTreePMap.empty(); HashPMap pmap0 = pmap.plus("key1", "value1"); Map map = new HashMap(); map.put("key2", "val2"); map.put("key3", "val3"); HashPMap pmap1 = pmap0.plusAll(map); HashPMap pmap2 = pmap1.minus("key1"); HashPMap pmap3 = pmap2.minusAll(map.keySet()); assertEquals(pmap0.size(), 1); assertEquals(pmap1.size(), 3); assertFalse(pmap2.containsKey("key1")); assertEquals(pmap3.size(), 0);
Важно отметить, что вызов put() on pmap вызовет исключение UnsupportedOperationException. Поскольку объекты коллекций являются постоянными и неизменяемыми, каждая операция изменения возвращает новый экземпляр объекта ( HashPMap ).
Давайте перейдем к рассмотрению других структур данных.
4. Структура списка (TreePVector и Constack)
TreePVector является постоянным аналогом java.util.ArrayList в то время как constack является аналогом java.util.LinkedList . TreePVector и ConsPStack имеют удобные статические методы для создания новых экземпляров – точно так же, как HashPMap .
Метод empty() создает пустой TreePVector , в то время как метод singleton() создает TreePVector только с одним элементом. Существует также метод from() , который можно использовать для создания экземпляра TreePVector из любого java.util.Коллекция .
Constack имеет статические методы с тем же именем, которые достигают той же цели.
TreePVector имеет методы для манипулирования им. Он имеет минус() и минус все() методы для удаления элемента(ов); pulse () и pulseall() для добавления элемента(ов).
with() используется для замены элемента с указанным индексом, а subList() получает диапазон элементов из коллекции.
Эти методы также доступны в Constack .
Давайте рассмотрим следующий фрагмент кода, который иллюстрирует методы, упомянутые выше:
TreePVector pVector = TreePVector.empty(); TreePVector pV1 = pVector.plus("e1"); TreePVector pV2 = pV1.plusAll(Arrays.asList("e2", "e3", "e4")); assertEquals(1, pV1.size()); assertEquals(4, pV2.size()); TreePVector pV3 = pV2.minus("e1"); TreePVector pV4 = pV3.minusAll(Arrays.asList("e2", "e3", "e4")); assertEquals(pV3.size(), 3); assertEquals(pV4.size(), 0); TreePVector pSub = pV2.subList(0, 2); assertTrue(pSub.contains("e1") && pSub.contains("e2")); TreePVector pVW = (TreePVector) pV2.with(0, "e10"); assertEquals(pVW.get(0), "e10");
В приведенном выше фрагменте кода pSub является другим объектом TreePVector и не зависит от pV2 . Как можно заметить, pV2 не был изменен операцией subList () ; вместо этого был создан новый TreePVector объект и заполнен элементами pV2 с индексом от 0 до 2.
Это то, что подразумевается под неизменяемостью, и это то, что происходит со всеми модифицирующими методами коллекций.
5. Структура набора (Набор карт)
Mapset -это постоянный, поддерживаемый картой аналог java.util.HashSet . Он может быть удобно создан статическими методами HashTreePSet – empty() , from() и singleton() . Они функционируют так же, как описано в предыдущих примерах.
Набор карт имеет плюс() , плюс все() , минус() и минус все() методы для манипулирования данными набора. Кроме того, он наследует методы из java.util.Set , java.util.AbstractCollection и java.util.Абстрактный набор :
MapPSet pSet = HashTreePSet.empty() .plusAll(Arrays.asList("e1","e2","e3","e4")); assertEquals(pSet.size(), 4); MapPSet pSet1 = pSet.minus("e4"); assertFalse(pSet1.contains("e4"));
Наконец, есть также OrderedPSet – который поддерживает порядок вставки элементов точно так же, как java.util.LinkedHashSet .
6. Заключение
В заключение, в этом кратком руководстве мы изучили PCollections – постоянные структуры данных, которые аналогичны основным коллекциям, доступным в Java. Конечно, коллекции Javadoc дают больше информации о тонкостях библиотеки.
И, как всегда, полный код можно найти на Github .