Перейти к основному содержимому

Введение в Javatuples

· 6 мин. чтения

1. Обзор

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

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

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

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

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

  • Единица <А>
  • Пара<A,B>
  • Триплет<А,В,С>
  • Квартет<A,B,C,D>
  • Квинтет<A,B,C,D,E>
  • Секстет<A,B,C,D,E,F>
  • Септет<A,B,C,D,E,F,G>
  • Октет<A,B,C,D,E,F,G,H>
  • Эннеада<A,B,C,D,E,F,G,H,I>
  • Десятилетие<A,B,C,D,E,F,G,H,I,J>

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

Согласно официальному сайту , все классы в 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);

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

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

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);

Как видим, позиция « джона » равна нулю, « 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"));

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

Приведенный выше пример также демонстрирует использование метода 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 .

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

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);

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

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

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));

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

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

assertThat(unit.contains(32));

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<Object>, даже если кортеж содержит элементы одного и того же типа.

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

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 и убедились в ее простоте. Он обеспечивает элегантную семантику и очень прост в использовании.

Обязательно ознакомьтесь с полным исходным кодом этой статьи на GitHub . Полный исходный код содержит немного больше примеров, чем представлено здесь. После прочтения этой статьи дополнительные примеры должны быть достаточно просты для понимания.