Как вставить «пару» или n-размер в коллекцию списков вместо того, чтобы составлять HashMaps? - PullRequest
0 голосов
/ 07 мая 2009

Итак, у меня есть ситуация, когда мне нужно передать три значения в последовательную очередь BlockingQueue:

(SelectableChannel, ComponentSocketBasis, Integer).

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

private LinkedBlockingQueue<HashMap<HashMap<SelectableChannel, ComponentSocketBasis>, Integer>> deferredPollQueue = new LinkedBlockingQueue<HashMap<HashMap<SelectableChannel, ComponentSocketBasis>, Integer>>();

Это кажется действительно смешным. Я должен быть ужасным n00b. Конечно, есть лучший способ сделать это, который не требует, чтобы я разлагал ключ при извлечении значений или тратил (теоретически - на практике, Java всегда раздутый :) алгоритмическая сложность на бесполезных хэш-вычислениях, которые мне не нужны потому что у меня есть пространство ключей 1 и я даже не хочу реляционно сопоставить три ссылки, а просто сгруппировать их? В этой реализации я должен вытащить значения следующим образом:

while(deferredPollQueue.size() > 0) {
    System.out.println("*** Draining new socket channel from queue");
    HashMap<HashMap<SelectableChannel, ComponentSocketBasis>, Integer> p = deferredPollQueue.take();

    SelectableChannel chan = null;
    ComponentSocketBasis sock = null;
    int ops = 0;

    HashMap<SelectableChannel, ComponentSocketBasis> q = p.keySet().iterator().next();

    chan = q.keySet().iterator().next();
    sock = q.get(chan);

    ops = p.get(q).intValue();

    SelectionKey k = chan.register(selector, ops);  

    if(!channelSupervisorMap.containsKey(k))
        channelSupervisorMap.put(k, sock);
}

Я почти уверен, что каждое существо, способное на разумную причину здесь, вероятно, думает, что это нелепый способ сделать это, поэтому вопрос в том - какой правильный путь? :) Я нигде не могу найти доказательства java.util.Pair или java.util.Triplet.

Я полагаю, что «Православный путь» (TM) должен был бы создать пользовательский класс или интерфейс только для того, чтобы вместить этот триплет, но для такой маленькой задачи в такой большой системе это кажется нелепо многословным и ненужным - хотя, опять же, это сама Java.

Точно так же, возможно, значения могут быть помещены в ArrayList или Vector или их производные, но в Java это не дает более краткого способа их решения, чем я выхожу из этой HashMap, хотя здесь это действительно решает проблему алгоритмической сложности, возможно.

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

push(@$big_queue_array, [$elem1, \%elem2, \@elem3]);

Какой лучший эквивалент в Java?

Ответы [ 4 ]

5 голосов
/ 07 мая 2009

Почему бы просто не создать свои собственные классы Pair или Triple? Практически каждый проект Java 5+ заканчивается тем, что они имеют свои собственные классы утилит!

4 голосов
/ 07 мая 2009

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

2 голосов
/ 07 мая 2009

Вы можете просто использовать ArrayList для хранения объектов, так как вы знаете, какой объект будет в каком месте. Создание нового класса с членами SelectableChannel и ComponentSocketBasis для, вероятно, будет лучше.

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

Всякий раз, когда вы видите свое имя класса в коде, вы точно знаете, для чего оно предназначено, тогда как, если вы просто видите свое общее объединение, вам (или кому-то еще) будет сложнее понять, для чего оно используется .

Это компромисс между временем программирования и удобочитаемостью.

2 голосов
/ 07 мая 2009

Функциональная Java имеет пары , триплеты и кортежи до арности 8. Также существует тип с именем HList для произвольная арность. Таким образом, ваш тип будет:

LinkedBlockingQueue<P3<SelectableChannel, ComponentSocketBasis, Integer>>

Это всего лишь библиотека, так что бросьте банку в свой путь к классу, и все готово.

...