AnyLogic
Развернуть
Размер шрифта

Коллекции

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

Список ArrayList

Список ArrayList (объект) — это простейшая коллекция в AnyLogic, которую можно рассматривать как изменяемый массив.

Следующая строка кода создает изначально пустой список ArrayList объектов класса Person:

ArrayList<Person> friends = new ArrayList<Person>();

Обратите внимание, что тип коллекции содержит тип элемента, заключенный в угловые скобки. Таким образом коллекция «настраивается» для работы с определенным типом элементов, вследствие чего, например, функция get() объекта friends вернет объект типа Person.

Функции

ArrayList предоставляет перечисленные ниже функции. Полное описание API приведено в справочнике классов AnyLogic.

Некоторые из приведенных функций относятся к примеру выше, в котором в качестве элементов, составляющих список массивов, используются объекты Person. Чтобы использовать их в собственных списках, укажите соответствующий тип объекта.
Функция Описание
int size() Возвращает количество элементов в списке.
boolean isEmpty() Проверяет данный список на отсутствие элементов.
Person get(int index) Возвращает элемент, находящийся на указанной позиции в списке.

index — Позиция, с которой нужно извлечь элемент.
boolean add(Person p) Добавляет указанный элемент в конец списка.

p — Элемент, который необходимо добавить.
Person remove(int index) Удаляет элемент, находящийся на указанной позиции в списке.

index — Позиция, из которой необходимо удалить элемент.
boolean contains(Person p) Возвращает true, если данный элемент содержится в списке.

p — Элемент, на наличие которого проводится проверка.
void clear() Удаляет все элементы из списка.

Примеры

  • Следующий фрагмент кода проверяет, содержит ли список friends элемент victor, и если нет, то добавляет его в список:
    if( ! friends.contains( victor ) )
      friends.add( victor );
  • Все типы коллекций поддерживают итерирование по элементам. Самой простой конструкцией для итерации является цикл for.
    Предположим, что у класса Person есть поле income. Приведенный ниже цикл распечатывает всех друзей с доходами больше 100000 в лог модели:
    or( Person p : friends ) {
      if( p.income > 100000 )
        traceln( p );
      }

Связный список

Связный список (объект LinkedList) — еще один популярный тип коллекции.

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

Рассмотрим модель, в которой дистрибьютор хранит журнал невыполненных заказов, полученных от ритейлеров. Предположим, есть класс Order с полем amount. Тогда журнал (являющийся, по сути, очередью FIFO: “первым пришёл — первым обслужен”) может быть промоделирован так:

LinkedList<Order> backlog = new LinkedList<Order>();

Функции

Класс LinkedList поддерживает общие для всех коллекций функции (такие как size() или isEmpty()), а также предлагает дополнительный набор методов.

Приведенные ниже функции относятся к примеру выше, в котором в качестве элементов, составляющих связный список, используются объекты Order. Чтобы использовать их в собственных связных списках, укажите соответствующий тип объекта.
Функция Описание
Order getFirst() Возвращает первый элемент списка.
Order getLast() Возвращает последний элемент списка.
addFirst(Order o) Вставляет заданный элемент в начало списка.

o — Элемент, который необходимо вставить.
addLast(Order o) Добавляет заданный элемент в конец списка.

o — Элемент, который необходимо добавить.
Order removeFirst() Возвращает первый элемент списка и удаляет его.
Order removeLast() Возвращает последний элемент списка и удаляет его.

Пример

Когда дистрибьютор получает новый заказ, он помещает его в конец списка невыполненных заказов:

backlog.addLast(order);

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

while(!backlog.isEmpty()) { // повторяем код ниже, пока журнал не пуст
  Order order = backlog.getFirst(); // берем первый заказ из журнала
  if(order.amount <= inventory) { // если достаточно товара, чтобы выполнить заказ
    ship(order); // выполняем заказ
    inventory -= order.amount; // уменьшаем количество товара на складе
    backlog.removeFirst(); // удаляем заказ из журнала
  } else { // если недостаточно товара,
    break; // прекращаем обработку журнала заказов
  }
}

Создание коллекций

Мы советуем задавать коллекции в агентах и экспериментах графически. Элемент Коллекция расположен в Основной палитре. Всё, что вам нужно сделать — это перетащить его из палитры на диаграмму и выбрать тип коллекции и тип элементов. Во время выполнения модели вы сможете просмотреть содержимое коллекции, щелкнув по её значку.

Графическое задание коллекции Java

Выбор типа коллекции

Различные типы коллекций имеют разную временную сложность операций. Например, проверка наличия заданного объекта в коллекции, содержащей 10 000 000 объектов, может потребовать 80 миллисекунд для коллекции типа ArrayList, 100 миллисекунд — для LinkedList, и менее 1 миллисекунды — для HashSet и TreeSet. Для обеспечения наибольшей эффективности необходимо исследовать, какие из операций наиболее часто выполняются, и выбрать соответствующий тип коллекции. В следующей таблице приведена временная сложность наиболее часто используемых операций для четырех типов коллекций.

Операция ArrayList LinkedList HashSet TreeSet
Получение размера Постоянная Постоянная Постоянная Постоянная
Добавление элемента Постоянная Постоянная Постоянная Логарифмическая
Удаление данного элемента Линейная Линейная Постоянная Логарифмическая
Удаление по индексу Линейная Линейная - -
Получение элемента по индексу Постоянная Линейная - -
Определение присутствия элемента в коллекции Линейная Линейная Постоянная Логарифмическая

Термины постоянная, линейная и логарифмическая сложность означают следующее:

  • Линейная сложность означает, что наихудшее время, необходимое для выполнения операции, растет линейно с увеличением размера коллекции.
  • Постоянная сложность означает, что время выполнения операции вообще не зависит от размера коллекции.
  • Логарифмическая сложность означает, что время выполнения операции растет параллельно логарифму ее размера.
Не следует рассматривать постоянную сложность как безусловно лучший выбор. В зависимости от размера разные типы коллекций могут вести себя лучше, чем другие.

Обратите внимание на приведенный ниже рисунок. Вполне может быть, что при относительно малом числе элементов коллекция с линейной сложностью будет работать лучше, чем коллекция с постоянной сложностью.

В зависимости от размера, одни типы коллекций могут вести себя лучше других

И пара моментов, которые следует знать при выборе типа коллекции:

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

Популяции агентов - это тоже коллекции

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

  • AgentArrayList  — Выберите этот тип коллекции, если набор агентов более или менее постоянен, или если необходимо часто обращаться к отдельным агентам по индексу.
  • AgentLinkedHashSet  — Выберите этот тип коллекции, если вы планируете часто добавлять новых агентов и удалять существующих. Например, если вы моделируете население города в течение относительно длительного периода времени, так что люди рождаются, умирают, уезжают из города, а новые люди прибывают.

Тип коллекции можно выбрать в секции свойств Специфические вложенного агента: см. рисунок ниже.

Выбор типа коллекции популяции агентов

Обе коллекции агентов поддерживают функции size(), isEmpty(), get(int index), contains(Object o) и итерацию по элементам. Если во время итерации не нужно оперировать со значением текущего индекса, то всегда лучше использовать упрощенную форму цикла for:

for(Person p : people) {
  …
}
Как мы можем улучшить эту статью?