如何将“Pair”或n-size插入到列表集合中而不是组成HashMap?
-
08-07-2019 - |
题
因此,我遇到一种情况,需要将三个值传递到串行 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 的证据。
我认为 Orthodox Way(TM) 会做一个自定义类或接口,只是为了容纳这个三元组,但是对于这么大的系统中的这么小的任务,这似乎是荒谬的冗长和不必要的——不过,话又说回来,那是Java本身。
出于同样的原因,也许可以将这些值放入 ArrayList 或 Vector 或其派生类中,但在 Java 中,这不会产生比我在这里从这个 HashMap 中得到的更简洁的寻址方式,尽管它确实解决了问题也许是算法复杂性问题。
回到 Perl 领域,我们只需使用数组引用作为数组内的值来完成此操作:
push(@$big_queue_array, [$elem1, \%elem2, \@elem3]);
Java 中最好的等效项是什么?
解决方案
为什么不创建自己的通用Pair或Triple类?几乎每个Java 5+项目最终都将它们放在自己的util类中!
其他提示
你说一个用于保存三元组的自定义类会变得臃肿而且不必要,但这确实是这样做的方式,这就是面向对象建模的工作原理。自定义类是显式且可读的,并且不会占用比通用持有者类更多的运行时资源。
您可以只使用 ArrayList 来存储对象,因为您知道哪个对象将位于哪个位置。使用成员 SelectableChannel 和 ComponentSocketBasis 创建一个新类可能会更好。
如果您要经常做这种事情,那么现在创建一个通用对或元组将为您节省大量时间,但如果这是您要使用它的唯一地方,那么创建一个新的类将使代码更容易阅读。
每当您在代码中看到类名时,您就会确切地知道它的用途,而如果您只看到通用合并,您(或其他人)可能很难理解它的用途。
这是编程时间和可读性之间的权衡。