Коллекции и структуры данных

Коллекции и структуры данных#

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

Список#

Список является изменяемым типом данных (mutable). Это значит, что можно добавлять и удалять элементы, а также изменять существующие.

Исходный массив для примера:

var mvStock = ["P-1001", "P-1002", "P-1003", ...];

Основные операции

Объявление списков:

var mvStockApproachOne = [...];

Добавление элементов (только для mutable):

mvStock.add("P-1004");

Получение элементов:

mvStock[0]; // способ 1
mvStock.get(0); // способ 2

Проверка наличия элемента:

mvStock.contains("P-1002"); // возвращает true/false

Удаление элементов (только для mutable):

mvStock.remove("P-1002");

Размер списка:

mvStock.size(); // возвращает количество элементов

Проверка на пустоту:

mvStock.isEmpty(); // возвращает true/false

Поиск индекса элемента:

mvStock.indexOf("P-1001"); // возвращает индекс или -1

Замена элемента (только для mutable):

mvStock.set(0, "newElement"); // способ 1
mvStock[0] = "newElement"; // способ 2

Объединение списков (только для mutable):

var listUnion = [1,2,3, ...];
mvStockApproachOne.addAll(listUnion);

Очистка списка (только для mutable):

mvStock.clear(); // удаляет все элементы

Массив#

Массив — это неизменяемая (immutable) структура данных с фиксированным размером. Вы не можете добавлять и удалять элементы, но можно изменять значения существующих элементов (если они сами по себе изменяемы).

Исходный массив для примера:

var mvStock = ["P-1001", "P-1002", "P-1003"];

Основные операции

Объявление массива:

var mvStockApproachOne = [];
var mvStockApproachTwo = [1, 2, 3];

Получение элементов:

mvStock[0]; // способ 1
mvStock.get(0); // способ 2

Проверка наличия элемента:

mvStock.contains("P-1002"); // возвращает true/false

Размер списка:

mvStock.size(); // количество элементов

Поиск индекса элемента:

mvStock.indexOf("P-1001"); // возвращает индекс или -1

Множество#

Доступны только mutable (изменяемые) множества. Основные операции

Создание множества:

var setData = {"P-1001", "P-1002", "P-1003"}; // Множество с элементами
var setEmptyData = {}; // Пустое множество

Добавление элементов:

setData.add("P-1004"); // Добавление одного элемента
setData.addAll({"P-1005", "P-1006"}); // Добавление другого множества
setData.addAll(["P-1007", "P-1008"]); // Добавление элементов из списка

При добавлении списка порядок элементов множества сбивается.

Проверка и получение элементов:

var exists = setData.contains("P-1001"); // Проверка наличия → true/false

Удаление элементов:

setData.remove("P-1001"); // Удаление по значению
setData.clear(); // Полная очистка множества

Работа с размерами:

var size = setData.size(); // Количество элементов
var isEmpty = setData.isEmpty(); // Проверка на пустоту → true/false

Операции с множествами:

// Пересечение (оставляет только общие элементы)
setData.retainAll({"P-1005", "P-1006"});

// Разность (удаляет элементы другого множества)
setData.removeAll({"P-1002", "P-1003"});

Карта#

Далее в примерах будем работать с этой картой:

var mapData = {"bwhasError" : 11, "svKeyTransaction" : 21}; // объявление словаря

Внимание

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

var mapData = {
    "bwhasError": 11,
    "svKeyTransaction": 21, // Это значение будет перезаписано
    "svKeyTransaction": 22 // Останется только это
};
// Итоговая карта: {"bwhasError": 11, "svKeyTransaction": 22}

Основные операции со словарями

Получение и добавление элемента:

mapData.e = 5; // добавление нового ключа (способ 1)
mapData.put("c", 3); // добавление нового ключа (способ 2)
mapData["d"] = 4; // добавление нового ключа (способ 3)

var approachTwo = mapData.bwhasError; // получение значения по ключу (способ 1)
var approachOne = mapData.get("bwhasError"); // получение значения по ключу (способ 2)
var approachThree = mapData["bwhasError"]; // получение значения по ключу (способ 3)

Получить и добавить значению по ключу можно тремя способами: через точку, квадратные скобки, метод get.

  • Точечная нотация работает только с ключами, которые являются валидными идентификаторами (без пробелов, дефисов, начинающиеся с буквы).

  • Для ключей со спецсимволами (тире, пробелы, точки) используйте квадратные скобки.

  • Методы put()/get() работают всегда, но требуют больше кода.

Пример с ограничениями:

var mvStock = {"P-1001" : 1, "P-1002" : 2, "P-1003" : 3};
var nCode = mvStock.P-1001; // Дефис воспримется как оператор

Проверка наличия ключа:

mapData.containsKey("bwhasError"); // возвращает true/false

Удаление элемента:

mapData.remove("bwhasError"); // удаляет пару "ключ-значение" по ключу

Размер словаря:

mapData.size(); // количество пар "ключ-значение"

Получение всех ключей:

mapData.keySet(); // возвращает массив ключей (например,["bwhasError", "svKeyTransaction"])

Получение всех значений:

mapData.values(); // возвращает массив значений (например, [11, 21])

Проверка на пустоту:

mapData.isEmpty(); // true, если карта пустая

Изменение значения по ключу:

mapData["bwhasError"] = 10; // присваивает новое значение ключу

Добавление новой пары «ключ-значение»:

mapData["newKey"] = 42; // добавляет новый ключ с значением

Очистка словаря:

mapData.clear(); // удаляет все элементы

Объединение словарей:

var newMap = {"key1": 1, "key2": 2};
mapData.addAll(newMap); // добавляет все пары из newMap в mapData (существующие ключи перезаписываются)

Операция entrySet:

var mapData = {"bwhasError" : 11, "svKeyTransaction" : 21};
var setMap = mapData.entrySet(); // Получаем множество пар ключ-значение

for (entry : setMap) { // Итерация по всем элементам (парам ключ-значение)
    var key = entry.getKey(); // Получить ключ текущей пары
    var value = entry.getValue(); // Получить значение текущей пары
}

Возвращает множество(Set) пар ключ-значение - объектов Map.Entry.

Каждый Entry содержит:

  • getKey() - уникальный ключ;

  • getValue() - соответствующее значение.

Перебор значений идет в обратном порядке.

Когда использовать entrySet():

  • Когда нужны и ключи, и значения в цикле.

  • Для модификации значений через entry.setValue().

  • Для получения «снимка» всех данных Map

Получение ключа по значению

Нет встроенной функции для получения ключа по значению, но можно написать свою локальную функцию для этой цели:

// Получения ключа по значению
var findKeysByValue = function(map, targetValue) {
    var matchedKeys = [...]; // Сюда будем складывать подходящие ключи
    for (let key : map.keySet()) { // Перебираем каждый ключ
        if (map[key] == targetValue) { // Если значение по ключу совпадает с искомым
            return key; // Добавляем ключ в результат
        }
    }
    return matchedKeys; // Возвращаем найденные ключи в виде списка
};

var keyListForValue = findKeysByValue(mapData, 11);
dialogs.showMessage(toString(keyListForValue));

По такому же принципу можно реализовать удаление ключа по значению.

Кортеж#

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

В JEXL отсутствует встроенный тип данных Кортеж (Tuple), но его можно эмулировать с помощью интеграции с Scala. Кортежи Tuple2 — это естественный способ передать такие данные из JEXL в Scala-код.

var tuple2 = (v1, v2) -> { return new(`scala.Tuple2`, v1, v2); };
  • new(scala.Tuple2, …) — создает экземпляр Scala-кортежа, используя JVM-интеграцию.

  • Функция принимает 2 аргумента и возвращает неизменяемую пару (v1, v2).

В Scala стандартные кортежи (Tuple) ограничены 22 элементами (до Tuple22):

var tuple22 = (v1, v2, v3,v4, v5, v6,v7, v8, v9,v10, v11, v12, v13, v14, v15,v16, v17, v18,v19, v20, v21,v22) -> {
    return new(`scala.Tuple22`, v1, v2, v3,v4, v5, v6,v7, v8, v9,v10, v11, v12, v13, v14, v15,v16, v17, v18,v19, v20, v21,v22);
};

dialogs.showMessage(toString(tuple22(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)));

Чтобы передавать параметры в Scala-коллекции, используем asScala():

// Массив пар [Имя_параметра, Значение]
var tuple2Params = asScala([
    tuple2("npInParam1", 10l), // Параметр 1 (Long)
    tuple2("npInParam2", 125l), // Параметр 2 (Long)
    tuple2("npInParam3", 1000l), // Параметр 3 (Long)
    ... // Остальные элементы (если есть)
]);

Особенности:

  • asScala() — преобразует JEXL-массив в Scala-коллекцию;

  • каждый элемент коллекции — кортеж («имя», значение).

Кортежи неизменяемы, что гарантирует:

  • параметры не поменяются случайно во время выполнения процедуры;

  • нет риска коллизий в многопоточных сценариях.