如何将“Pair”或n-size插入列表集合而不是组成HashMaps?

时间:2009-05-07 15:32:48

标签: java collections map dataset queue

所以,我有一种情况需要将三个值传入一个串行的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 land,我们只是通过使用数组引用作为数组中的值来实现这一点:

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

Java中最好的等价物是什么?

4 个答案:

答案 0 :(得分:5)

为什么不创建自己的通用Pair或Triple类?几乎每个Java 5+项目最终都将它们放在自己的util类中!

答案 1 :(得分:4)

你说一个用于保存三元组的自定义类会变得臃肿而且不必要,但这确实是这样做的方式,这就是面向对象建模的工作原理。自定义类是显式且可读的,并且不会占用比通用持有者类更多的运行时资源。

答案 2 :(得分:2)

Functional Javapairstriplets,元组最多为arity 8.还有一个名为HList的类型用于仲裁。所以你的类型是:

LinkedBlockingQueue<P3<SelectableChannel, ComponentSocketBasis, Integer>>

这只是一个库,所以将jar放在类路径中,你就可以了。

答案 3 :(得分:2)

您可以使用ArrayList来存储对象,因为您知道哪个对象将位于哪个位置。使用成员SelectableChannel和ComponentSocketBasis创建一个新类可能会更好。

如果您要做很​​多这样的事情,现在创建一个通用对或元组将为您节省大量时间,但如果这是您将要使用它的唯一地方,那么创建一个新类将使代码更容易阅读。

每当你在代码中看到你的类名时,你就会知道它的确切含义,而如果你只看到你的通用合并,那么你(或其他人)可能更难理解它的用途是什么

这是编程时间和可读性之间的权衡。