«1. Обзор

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

Например, [\»RAM\», 16, \»Astra\»] — это кортеж, содержащий три элемента.

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

2. Встроенные классы Javatuples

Эта библиотека предоставляет нам десять различных классов, которых достаточно для большинства наших требований, связанных с кортежами:

    Unit\u003cA\u003e Pair\u003cA,B\u003e Triplet\u003cA,B, C\u003e Квартет\u003cA,B,C,D\u003e Квинтет\u003cA,B,C,D,E\u003e Секстет\u003cA,B,C,D,E,F\u003e Септет\u003cA,B,C,D,E, F,G\u003e Октет\u003cA,B,C,D,E,F,G,H\u003e Эннеада\u003cA,B,C,D,E,F,G,H,I\u003e Декада\u003cA,B,C, D,E,F,G,H,I,J\u003e

В дополнение к вышеперечисленным классам есть два дополнительных класса, KeyValue\u003cA,B\u003e и LabelValue\u003cA,B\u003e, которые предоставляют функциональные возможности, аналогичные Pair. \u003cA,B\u003e, но отличаются по семантике.

Согласно официальному сайту, все классы в javatuples типобезопасны и неизменяемы. Каждый из классов кортежей реализует интерфейсы Iterable, Serializable и Comparable.

3. Добавление зависимости Maven

Давайте добавим зависимость Maven в наш pom.xml:

<dependency>
    <groupId>org.javatuples</groupId>
    <artifactId>javatuples</artifactId>
    <version>1.2</version>
</dependency>

Пожалуйста, проверьте наличие последней версии в центральном репозитории Maven.

4. Создание кортежей

Создать кортеж очень просто. Мы можем использовать соответствующие конструкторы:

Pair<String, Integer> pair = new Pair<String, Integer>("A pair", 55);

Существует также немного менее подробный и семантически элегантный способ создания кортежа:

Triplet<String, Integer, Double> triplet = Triplet.with("hello", 23, 1.2);

Мы также можем создавать кортежи из Iterable:

List<String> listOfNames = Arrays.asList("john", "doe", "anne", "alex");
Quartet<String, String, String, String> quartet
  = Quartet.fromCollection(collectionOfNames);

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

Однако мы можем создать кортеж более низкого порядка, такой как Pair или Triplet, используя приведенную выше коллекцию, указав начальный индекс в методе fromIterable():

Pair<String, String> pairFromList = Pair.fromIterable(listOfNames, 2);

Приведенный выше код приведет к созданию пары, содержащей «Энн» и «Алекс».

Кортежи также удобно создавать из любого массива:

String[] names = new String[] {"john", "doe", "anne"};
Triplet<String, String, String> triplet2 = Triplet.fromArray(names);

5. Получение значений из кортежей

Каждый класс в javatuples имеет метод getValueX() для получения значений из кортежей, где X указывает порядок элементов внутри кортежа. Как и индексы в массивах, значение X начинается с нуля.

Давайте создадим новый квартет и получим некоторые значения:

Quartet<String, Double, Integer, String> quartet 
  = Quartet.with("john", 72.5, 32, "1051 SW");

String name = quartet.getValue0();
Integer age = quartet.getValue2();
 
assertThat(name).isEqualTo("john");
assertThat(age).isEqualTo(32);

Как мы видим, позиция «john» равна нулю, «72,5» равна единице и так далее.

Обратите внимание, что методы getValueX() типобезопасны. Это означает, что литье не требуется.

Альтернативой этому является метод getValue(int pos). Требуется отсчитываемая от нуля позиция элемента, который нужно извлечь. Этот метод не является типобезопасным и требует явного приведения типов:

Quartet<String, Double, Integer, String> quartet 
  = Quartet.with("john", 72.5, 32, "1051 SW");

String name = (String) quartet.getValue(0);
Integer age = (Integer) quartet.getValue(2);
 
assertThat(name).isEqualTo("john");
assertThat(age).isEqualTo(32);

Обратите внимание, что классы KeyValue и LabelValue имеют соответствующие методы getKey()/getValue() и getLabel()/getValue().

6. Установка значений для кортежей

Подобно getValueX(), все классы в javatuples имеют методы setAtX(). Опять же, X — это отсчитываемые от нуля позиции для элемента, который мы хотим установить:

Pair<String, Integer> john = Pair.with("john", 32);
Pair<String, Integer> alex = john.setAt0("alex");

assertThat(john.toString()).isNotEqualTo(alex.toString());

Здесь важно то, что возвращаемый тип метода setAtX() — это сам тип кортежа. Это потому, что javatuples неизменяемы. Установка любого нового значения оставит исходный экземпляр нетронутым.

7. Добавление и удаление элементов из кортежей

Мы можем удобно добавлять новые элементы в кортежи. Однако это приведет к созданию нового кортежа на порядок выше:

Pair<String, Integer> pair1 = Pair.with("john", 32);
Triplet<String, Integer, String> triplet1 = pair1.add("1051 SW");

assertThat(triplet1.contains("john"));
assertThat(triplet1.contains(32));
assertThat(triplet1.contains("1051 SW"));

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

Пример выше также демонстрирует использование метода contains(), предоставленного всеми классами в javatuples. Это действительно удобный метод для проверки того, содержит ли кортеж заданное значение.

Также можно добавить один кортеж к другому с помощью метода add():

Pair<String, Integer> pair1 = Pair.with("john", 32);
Pair<String, Integer> pair2 = Pair.with("alex", 45);
Quartet<String, Integer, String, Integer> quartet2 = pair1.add(pair2);

assertThat(quartet2.containsAll(pair1));
assertThat(quartet2.containsAll(pair2));

«

«Обратите внимание на использование метода containsAll(). Он вернет true, если все элементы пары1 присутствуют в квартете2.

Pair<String, Integer> pair1 = Pair.with("john", 32);
Triplet<String, String, Integer> triplet2 = pair1.addAt1("1051 SW");

assertThat(triplet2.indexOf("john")).isEqualTo(0);
assertThat(triplet2.indexOf("1051 SW")).isEqualTo(1);
assertThat(triplet2.indexOf(32)).isEqualTo(2);

По умолчанию метод add() добавляет элемент в качестве последнего элемента кортежа. Тем не менее, можно добавить элемент в заданную позицию с помощью метода addAtX(), где X — это отсчитываемая от нуля позиция, в которую мы хотим добавить элемент:

В этом примере строка добавляется в позицию 1, который затем проверяется методом indexOf(). Обратите внимание на разницу в порядке типов для Pair\u003cString, Integer\u003e и Triplet\u003cString, String, Integer\u003e после вызова метода addAt1().

Pair<String, Integer> pair1 = Pair.with("john", 32);
Quartet<String, Integer, String, Integer> quartet1 = pair1.add("alex", 45);

assertThat(quartet1.containsAll("alex", "john", 32, 45));

Мы также можем добавить несколько элементов, используя любой из методов add() или addAtX():

Pair<String, Integer> pair1 = Pair.with("john", 32);
Unit<Integer> unit = pair1.removeFrom0();

assertThat(unit.contains(32));

Чтобы удалить элемент из кортежа, мы можем использовать метод removeFromX(). Опять же, X указывает отсчитываемую от нуля позицию удаляемого элемента:

8. Преобразование кортежей в список/массив

Quartet<String, Double, Integer, String> quartet
  = Quartet.with("john", 72.5, 32, "1051 SW");
List<Object> list = quartet.toList();

assertThat(list.size()).isEqualTo(4);

Мы уже видели, как преобразовать список в кортеж. Давайте теперь посмотрим, как преобразовать кортеж в список:

Это довольно просто. Единственное, что здесь следует отметить, это то, что мы всегда будем получать List\u003cObject\u003e, даже если кортеж содержит элементы одного и того же типа.

Quartet<String, Double, Integer, String> quartet
  = Quartet.with("john", 72.5, 32, "1051 SW");
Object[] array = quartet.toArray();

assertThat(array.length).isEqualTo(4);

Наконец, давайте преобразуем кортеж в массив:

Достаточно ясно, что метод toArray() всегда возвращает Object[].

9. Заключение

В этой статье мы рассмотрели библиотеку javatuples и убедились в ее простоте. Он обеспечивает элегантную семантику и очень прост в использовании.