Java хранение пар значений

Как хранить массив пар в Java?

Как инициализировать переменную пары? Есть ли лучшая структура для хранения моего массива пар двойных чисел?

8 ответов

Создайте свой собственный класс для представления пары и добавьте конструктор, который принимает два аргумента:

public class MyPair < private final Double key; private final Double value; public MyPair(Double aKey, Double aValue) < key = aKey; value = aValue; >public Double key() < return key; >public Double value() < return value; >> 

См. этот ответ по причинам, почему Pair не существует в Java: Что такое эквивалент С++ Pair < L, R >в Java?

Я удивлен, что в стандартной библиотеке Java нет ничего, что я мог бы использовать для такой простой вещи

Посмотрите этот ответ по причинам, почему такой Pair существует: stackoverflow.com/questions/156275/…

обратите внимание, что это решение значительно увеличивает сложность проекта, поскольку у вас может быть 100 различных классов, которые фактически являются парами, но у каждого есть свой тип; Требование настраиваемого распределения между типами, которое подвержено ошибкам, выглядит некрасиво и дорого (так как вы не можете перехватывать данные от одного к другому, и враждебность кеша). Это нормально, если все пары реализовали свои собственные маршаллеры, это решает все проблемы, кроме производительности и разных версий пары, имеющих базовый интерфейс с разными именами, которые можно решить, не имея интерфейса и используя отражение, но теперь у вас есть другие проблемы.

Вы не хотите использовать Entry it INTERFACE, а не CLASS. Этот интерфейс используется реализацией Set, когда вы вызываете entrySet() для класса, реализующего Map. Это в основном позволяет вам манипулировать реализованной Map, как если бы это был Set.

Читайте также:  Switch для массива php

Что бы вы сделали (но не можете), это. Если вы попытаетесь сделать это, вы увидите ошибку компилятора в строках «Невозможно создать экземпляр типа Map.Entry». Это потому, что Map.Entry — это интерфейс, а не класс. Интерфейс не содержит реального кода, поэтому здесь нет реального конструктора.

Если вы посмотрите на приведенные ниже документы, вы можете ясно видеть вверху, что это «Интерфейс Map.Entry», что означает его интерфейс. http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Map.Entry.html

Что вы должны сделать, а не пытаться создать экземпляр интерфейса, что невозможно, это создать свой собственный класс под названием Pair. Что-то вроде этого. Не забудьте изменить пакет, если вы используете приведенный ниже код.

package org.mike.test; public class Pair < private double x = 0.0; private double y = 0.0; public Pair(double x, double y) < this.x = x; this.y = y; >public Pair() < >public double getX() < return x; >public void setX(double x) < this.x = x; >public double getY() < return y; >public void setY(double y) < this.y = y; >> 

После написания вашего класса Pair ваш код будет выглядеть следующим образом.

package org.mike.test; import java.util.ArrayList; import org.mike.test.Pair; //You don't need this if the Pair class is in the same package as the class using it public class tester < /** * @param args */ public static void main(String[] args) < ArrayListvalues = new ArrayList(); Pair pair = new Pair(); // set pair values: pair.setY(3.6); pair.setX(3.6); values.add(pair); > > 

Хорошо, и представьте, что вы дали нам конструктор Pair (double, double), я бы упростил и удалил вызовы setX / Y () и использовал Pair pair = new Pair (3.6, 3.6);

Не могли бы вы просто использовать

public class MyClass extends ArrayList < private A first; private B second; public MyClass(A first, B second)< super(); this.first = first; this.second = second;>> 

а затем добавить некоторую форму метода add, а также первый и второй методы доступа и мутатора? Я как бы новичок в программировании, но, похоже, это может сработать и быть доступным для вещей, отличных от DOUBLE (в случае, если вы хотите использовать другие типы, такие как Integer или даже String).

Является ли Entry классом, который вы определили? Вы создаете экземпляр с помощью new .

Entry pair = new Entry(d1, d2); 

Примечание. Я предполагаю, что вы определили конструктор, который принимает 2 удвоения, и у вас есть ссылки для d1 и d2 .

Я предлагаю вам НЕ использовать класс Map.Entry . Семантика для этого класса такова, что значения являются ключом и значением, соответствующим способу работы Карт.

Источник

Кортежи объектов в Java и их коллекции

Достаточно часто на практике возникает необходимость воспользоваться такими конструкциями как «пара» ( Pair ), менее часто «тринарными» объектами ( Triplet ) и более длинными цепочками ассоциированных объектов. В связи с чем всегда удивлялся, почему в JDK (в java.lang.* или java.util.* ) до настоящего момента нет стандартной Pair или более длинных конструкций. Думаю многие программисты практикующие на Java имеют свою реализацию «пары». Не исключением являюсь и я.

И вот в очередной раз наткнувшись на необходимость работать с большим количеством различных кортежей, решил взяться за эту проблему системно. Придумал название проекту, определил цели и после экспериментов, занявших некоторое время, выложил код ( git://github.com/telesik/rumba.git ).

  • Необходима удобная конструкция (назовем ее кортеж) для ассоциации нескольких объектов, типы которых определялись бы из позиции в полученном кортеже;
  • Кортеж должен быть неограниченным по длине и типу;
  • Типы элементов должны быть относительно контролируемым (как минимум ограничен дженериками);
  • Описание структуры кортежа должно быть простым;

Явление на свет кортежа

public interface Cortege  < T setValue(V value); T nextElement(); Vi getValue(int index) throws ClassCastException; // be careful with types. Type is not bounded int getDeep(); void setValue(int index, Vi value); // be careful with types. Type is not bounded Cortege setValues(Object. values); // be careful with types. Type is not bounded. V getValue(); static abstract class End implements Cortege  < >> 

image

На рисунке ниже наглядно показан механизм описания кортежей произвольной длины и типов элементов

Рис. 1. механизм описания кортежей произвольной длины и типов элементов

Но что есть “голый” интерфейс, если нет ни одной реализации? Есть такая! Имя ей CortegeChain . Наличие в названии слова Chain обусловлено способом организации хранения элементов в кортеже. Предполагаю и надеюсь, что в будущем появятся другие реализации, оптимизированные для различных типов использования.
В реализации CortegeChain я не ставил особых целей оптимизации с точки зрения использования памяти или скорости работы. Основной задачей, которую я хотел решить — это попробовать саму идею, найти слабые места, обозначить очевидные и не очевидные возможности, открывающиеся перед разработчиком.

Примеры использования

Перейду сразу к наглядным примерам использования:

// создание инстанса кортежа: Cortege> cortegeLS = CortegeChain.create(2); 

Следует обратить внимание на аргумент метода create. В связи с тем, что в Java дженерики существуют лишь на этапе компиляции, и добраться к ним в runtime я «законных» методов не нашел :(, пришлось «заплатить» за это такой ценой. Суть этого параметра — декларация глубины создаваемого кортежа. Но в виду того, что разработчик как правило знает кол-во элементов, необходимость указания этого параметра не должно вызывать больших проблем.

примечание: Но все же, если кто-то может предложить свое решение это проблемки с параметром — я буду чрезвычайно благодарен.

// заполнение элементов значениями // 1-й вариант (заполняем первый элемент в кортеже, с контролем типа) cortegeLS.setValue(4L); cortegeLS.nextElement().setValue("str"); // 2-й вариант (заполняем подряд цепью, с контролем типа) cortegeLS.setValue(4L).setValue("str"); // 3-й вариант (заполняем массивом, без контроля типа) cortegeLS.setValues(4L, "str"); 
// 1-й вариант (чтение первого элемента в кортеже, с контролем типа) Long valueA = cortegeLS.getValue(); // 2-й вариант (чтение выбранного элемента в кортеже, с контролем типа) String valueB = cortegeLS.nextElement().getValue(); // 3-й вариант (чтение выбранного элемента в кортеже, без контроля типа) Long valueC = cortegeLS.getValue(1); String valueD = cortegeLS.getValue(2); 
Cortege rightCortegeS = cortegeLS.nextElement(); // еще раз Cortege.End rightCortegeEnd = cortegeLS.nextElement().nextElement(); 
int deep = cortegeLS.getDeep(); 

Коллекции кортежей

Создавал я кортеж не просто так. Теперь имея такую конструкцию хорошо бы ее «прикрутить» к дружному семейству коллекций ( java.util.Collection ). Сказано — сделано. Но банальное использование кортежа как элемента коллекции не интересно. Хочется не просто находить, удалять, модифицировать элементы коллекции вцелом, что дают традиционные реализации интерфейсов java.util.Set и java.util.List , но и искать, фильтровать по отдельным элементам кортежей, хранящимся в коллекции, модифицировать колонки целиком и т.п, что является естественным для реляционных таблиц.

  • Коллекция должна быть совместима с давно ставшими стандартом интерфейсами семейства java.util.Collection (такими как java.util.Set и java.util.List )
  • Имплементация должна расширять функционал своих аналогов в мире простых объектов (например таких как java.util.HashSet );
  • В коллекции должно быть легко искать по абстрактному критерию;
  • Необходимо реализовать получение подмножества;
  • Очень хотелось бы реализовать возможность создания представления (аналог view в реляционных базах) над коллекцией.
    • представление не “владеет” исходными данными, а лишь фильтрует оригинальную коллекцию согласно критерию
    • фильтрация должна быть не одноразовой, а динамической. т.е. должна быть актуальной и отражать состояние оригинальной таблицы. все вставки, модификации и удаления из коллекции должны отражаться в ее представлении согласно предикату наложенному на view.

    public interface CortegeCollection extends Collection, Iterable < boolean contains(int num, T obj); CortegeCollection extract(int num, Object key); CortegeCollection extract(Corteges.Predicate predicate); // CortegeCollection view(int num, Corteges.Predicate predicate); T findAny(int num, Object key); T findAny(Corteges.Predicate predicate); List getColumnCopy(int num); void fill(int num, Vi value); > public interface CortegeSet extends CortegeCollection, Set < >public interface CortegeList extends CortegeCollection, List

    image

    Рис. 2. Топология кортежных коллекций

    Примеры использования коллекций кортежей

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

    public class ExampleCollections < public static void main(String[] args) < // Создание экземпляра CortegeHashSet CortegeSet>> cortegeHashSetLS = Corteges.newCortegeHashSet(2); for (long i = 0; i < 5; i++) < Cortege> cortegeLS = CortegeChain.create(2); cortegeLS.setValue(i).setValue("" + i); cortegeHashSetLS.add(cortegeLS); > for (Cortege cortege : cortegeHashSetLS) < System.out.println(cortege); >cortegeHashSetLS.add(CortegeChain.>create(2)); Cortege> cortegeIS = CortegeChain.create(2); System.out.println(cortegeHashSetLS.contains(cortegeIS)); cortegeIS.setValue(null).setValue("3"); System.out.println(cortegeIS); System.out.println(cortegeHashSetLS.contains(cortegeIS)); System.out.println(cortegeHashSetLS.contains(1, 3L)); Cortege> cortegeLLS1 = CortegeChain.create(3); Cortege> cortegeLLS2 = CortegeChain.create(3); Cortege> cortegeLLS3 = CortegeChain.create(3); CortegeChain>> cortegeSLS = CortegeChain.create(3); cortegeLLS1.setValue(1L); cortegeLLS1.nextElement().setValue(11L); cortegeLLS1.nextElement().nextElement().setValue("AAA"); cortegeLLS2.setValue(2L); cortegeLLS2.nextElement().nextElement().setValue("BBB"); cortegeLLS3.setValue(3L); cortegeLLS3.nextElement().setValue(33L); cortegeLLS3.nextElement().nextElement().setValue("AAA"); CortegeHashSet>> cortegeSetLLS = Corteges.newCortegeHashSet(cortegeLLS1.getDeep()); System.out.println(cortegeSetLLS.contains(cortegeLLS1)); cortegeSetLLS.add(cortegeLLS1); cortegeSetLLS.add(cortegeLLS2); cortegeSetLLS.add(cortegeLLS3); System.out.println(cortegeSetLLS.contains(cortegeLLS1)); for (Cortege> cortege : cortegeSetLLS) < System.out.println(cortege); >System.out.println(cortegeSetLLS.contains(3, "AAA")); cortegeSetLLS.fill(1, 5L); cortegeSetLLS.fill(2, 8L); cortegeSetLLS.fill(3, "XXX"); for (Cortege> cortege : cortegeSetLLS) < System.out.println(cortege); >// Collection corteges = cortegeSetLLS.extract(2, "111"); > > 

    Подведем итоги

    • Создание кортежа произвольной длины достаточно просто и сводится лишь к перечислению типов элементов составляющих будущий экземпляр кортежа
    • При последовательном обращении к элементам кортежа контролируется тип элемента
    • Благодаря выбранной структуре декларации и хранения кортежа возможно получение под-кортежа «справа» (метод nextElement() )
    • Есть возможность найти кортеж или подмножество кортежей в коллекции по простому критерию эквивалентности элемента эталонному объекту (методы extract(int num, Object key) и findAny(int num, Object key))
    • Есть возможность найти кортеж или подмножество кортежей в коллекции по предикату (методы extract(Corteges.Predicate predicate) и findAny(Corteges.Predicate predicate))
    • Есть возмодность получить любую колонку с указанным номером образованную из элементов кортежей коллекции
    • Есть возмодность заполнить целиком колонку элементов
    • Unit (1 element)
    • Pair (2 elements)
    • Triplet (3 elements)
    • Quartet (4 elements)
    • Quintet (5 elements)
    • Sextet (6 elements)
    • Septet (7 elements)
    • Octet (8 elements)
    • Ennead (9 elements)
    • Decade (10 elements)

    Заключение

    Работая над библиотекой я старался покрыть наиболее типичные, и с моей точки зрения, полезные задачи, возникающие при работе с кортежами и их коллекциями. К сожалению не все планы реализовано, но надеюсь та толика работы, что была выполнена будет кому-нибудь полезна. Но работа продолжается, надеюсь не зря.
    Было бы очень интересно получить конструктивный фитбэк на эту статью и библиотеку.

    Источник

Оцените статью