Коллекции

При разработке программ нам часто приходится работать с множествами.

И мы уже обсуждали этот вопрос в теме Массивы, однако, количество элементов которое можно хранить в массиве - фиксированное.

Например:
public class Main { public static void main(String[] args) { int[] nums = {3,4,5}; nums[2] = 2; nums[3] = 9; // Ошибка (Index 3 out of bounds for length 3) } }

Из примера видно, что на момент создания массив имеет длину 3 и записать ещё один элемент не получится, мы получаем ошибку.

Какой можно найти выход из ситуации?

Давайте попробуем реализовать класс для создания массива, в который можно будет добавлять произвольное количество элементов!

Будем использовать следующие идеи:
  1. Внутренний массив: Используем обычный массив для хранения элементов.

  2. Изменение размера: При заполнении массива создаем новый массив большего размера и копируем в него все элементы.

  3. Методы:

    • add() — добавление элемента.

    • get() — получение элемента по индексу.

    • remove() — удаление элемента по индексу.

    • size() — получение текущего размера массива.

    • resize() — увеличение размера внутреннего массива.

Реализация:
public class DynamicArray { private int[] array; // Внутренний массив для хранения элементов private int size; // Текущее количество элементов в массиве // Конструктор по умолчанию (начальный размер массива — 10) public DynamicArray() { array = new int[10]; size = 0; } // Конструктор с указанием начальной емкости public DynamicArray(int initialCapacity) { if (initialCapacity < 0) { throw new IllegalArgumentException("Начальная емкость не может быть отрицательной"); } array = new int[initialCapacity]; size = 0; } // Добавление элемента в конец массива public void add(int element) { // Если массив заполнен, увеличиваем его размер if (size == array.length) { resize(); } array[size] = element; size++; } // Получение элемента по индексу public int get(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Индекс выходит за пределы массива"); } return array[index]; } // Удаление элемента по индексу public void remove(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Индекс выходит за пределы массива"); } // Сдвигаем все элементы влево, начиная с удаляемого for (int i = index; i < size - 1; i++) { array[i] = array[i + 1]; } size--; } // Получение текущего размера массива public int size() { return size; } // Увеличение размера внутреннего массива private void resize() { int newCapacity = array.length * 2; // Увеличиваем размер в 2 раза int[] newArray = new int[newCapacity]; // Копируем элементы из старого массива в новый for (int i = 0; i < array.length; i++) { newArray[i] = array[i]; } array = newArray; } // Вывод массива в виде строки (для удобства тестирования) @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < size; i++) { sb.append(array[i]); if (i < size - 1) { sb.append(", "); } } sb.append("]"); return sb.toString(); } // Пример использования public static void main(String[] args) { DynamicArray dynamicArray = new DynamicArray(5); // Добавляем элементы dynamicArray.add(10); dynamicArray.add(20); dynamicArray.add(30); dynamicArray.add(40); dynamicArray.add(50); dynamicArray.add(60); // Массив увеличится в размере System.out.println("Массив после добавления элементов: " + dynamicArray); // Получаем элемент по индексу System.out.println("Элемент с индексом 2: " + dynamicArray.get(2)); // Удаляем элемент по индексу dynamicArray.remove(1); System.out.println("Массив после удаления элемента с индексом 1: " + dynamicArray); // Выводим текущий размер массива System.out.println("Текущий размер массива: " + dynamicArray.size()); } }
Описание работы методов:
  1. Внутренний массив (array):

    • Используется для хранения элементов.

    • Изначально создается с фиксированной емкостью (по умолчанию 10).

  2. Метод add(int element):

    • Добавляет элемент в конец массива.

    • Если массив заполнен, вызывается метод resize(), который увеличивает его размер.

  3. Метод resize():

    • Создает новый массив с удвоенной емкостью.

    • Копирует все элементы из старого массива в новый.

  4. Метод get(int index):

    • Возвращает элемент по указанному индексу.

    • Если индекс выходит за пределы массива, выбрасывается исключение IndexOutOfBoundsException.

  5. Метод remove(int index):

    • Удаляет элемент по указанному индексу.

    • Все последующие элементы сдвигаются влево.

  6. Метод size():

    • Возвращает текущее количество элементов в массиве.

  7. Метод toString():

    • Переопределен для удобного вывода массива в виде строки.

СЛОЖНААА!!! - не так ли?

Если данный подход показался громоздким и сложным, то так оно и есть.

На самом деле, задача создания динамических массивов встречается невероятно часто.

Несколько примеров:
  • Вывод списка товаров из базы данных (их кол-во мы можем не знать заранее).
  • Сохранение списка элементов при парсинге сайтов.
  • и другие случаи, когда мы не можем заранее знать кол-во элементов.

Ну и раз эта задача встречается часто, значит наверняка уже имеются красивые и изящные решения!


Коллекции

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

В Java коллекции представлены в виде набора интерфейсов и классов, которые находятся в пакете java.util.

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

Иерархия коллекций

Иерархия коллекций в Java строится на основе нескольких ключевых интерфейсов:

Описание интерфейсов и классов
Interface:
  1. Collection:

    • Базовый интерфейс для всех коллекций.

    • Основные методы: add(), remove(), size(), isEmpty(), contains().

  2. List:

    • Упорядоченная коллекция, которая позволяет хранить дубликаты.

    • Основные реализации: ArrayList, LinkedList, Vector.

  3. Set:

    • Коллекция, которая не позволяет хранить дубликаты.

    • Основные реализации: HashSet, LinkedHashSet, TreeSet.

  4. Queue:

    • Коллекция, предназначенная для хранения элементов в порядке, который зависит от реализации (например, FIFO).

    • Основные реализации: PriorityQueue, ArrayDeque.

  5. Map:

    • Коллекция, которая хранит данные в виде пар "ключ-значение".

    • Основные реализации: HashMap, LinkedHashMap, TreeMap, Hashtable.

Class:
  1. ArrayList:

    • Динамический массив, который автоматически увеличивает свой размер.

    • Быстрый доступ по индексу, но медленные вставка и удаление в середине списка.

  2. LinkedList:

    • Двусвязный список.

    • Быстрые вставка и удаление, но медленный доступ по индексу.

  3. HashSet:

    • Хранит уникальные элементы без гарантии порядка.

    • Основан на хэш-таблицах.

  4. TreeSet:

    • Хранит уникальные элементы в отсортированном порядке.

    • Основан на красно-черном дереве.

  5. HashMap:

    • Хранит пары "ключ-значение".

    • Быстрый доступ по ключу.

  6. TreeMap:

    • Хранит пары "ключ-значение" в отсортированном порядке по ключам.


Итак, мы познакомились с таким понятием, как коллекции. Теперь необходимо изучить методы, с помощью которых можно управлять коллекциями, и посмотреть на их практическое применение!

Об этом поговорим далее.


Комментарии

Добавить комментарий

Чтобы оставить комменатрий необходимо Авторизоваться