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 . Полный исходный код содержит немного больше примеров, чем представлено здесь. После прочтения этой статьи дополнительные примеры должны быть достаточно просты для понимания.