Question

So, I have a situation where I need to pass in three values into a serial BlockingQueue queue:

(SelectableChannel, ComponentSocketBasis, Integer).

They don't actually need to be hash mapped at all, and to use a HashMap is ridiculous as there will always be only one key for each entry; it'd be fine if they were just in some sort of ordered set. For lack of a known alternative, however, I used a HashMap in my implementation and produced this obfuscated generics composition:

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

This seems really ridiculous. I must be a terrible n00b. Surely there is a better way to do this that doesn't require me to decompose the key when retrieving the values or waste the (theoretical--in practice, Java's always bloated :) algorithmic complexity on a useless hash computation I don't need because I have a key space of 1 and don't even want to relationally map the three references, but merely to group them? With this implementation, I have to pull out the values thusly:

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);
}

I am pretty sure every being capable of sentient reason here probably thinks this is a ridiculous way to do it, so the question is - what's the right way? :) I can't find evidence of a java.util.Pair or java.util.Triplet anywhere.

I suppose an Orthodox Way(TM) would be to do a custom class or interface just for the purpose of housing this triplet, but for such a small task in such a large system this seems preposterously verbose and unecessary--though, then again, that's Java itself.

By the same token, perhaps the values can be put onto an ArrayList or a Vector or derivative thereof, but in Java this does not yield a more terse way of addressing them than I'm getting out of this HashMap here, though it does solve the algorithmic complexity issue perhaps.

Back in Perl land, we'd just do this by using an array reference as a value inside an array:

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

What's the best equivalent in Java?

Was it helpful?

Solution

Why not just create your own generic Pair or Triple classes? Pretty much every Java 5+ project ends up having them in their own util classes!

OTHER TIPS

You say that a custom class to hold the triplet would be bloated and unnecessary, but this really is the way to do it, that's how object-oriented modelling works. A custom class is explicit and readable, and takes up no more runtime resources than a generic holder class would.

Functional Java has pairs, triplets, and tuples up to arity 8. There's also a type called HList for arbitary arity. So your type would be:

LinkedBlockingQueue<P3<SelectableChannel, ComponentSocketBasis, Integer>>

This is just a library, so drop the jar in your classpath and you're good to go.

You could just use an ArrayList to store the objects, since you know which object will be at which location. Creating a new class with the members SelectableChannel and ComponentSocketBasis for the would probably be better.

If you're going to be doing this kind of thing a lot, creating a generic pair or tuple now will save you a lot of time, but if this is the only place you're going to be using it, then creating a new class will result in much easier to read code.

Whenever you see your classname in the code, you'll know exactly what it's for, whereas if you just see your generic amalgamation, it might be harder for you (or someone else) to make sense of what it's being used for.

It's a tradeoff between programming time and readability.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top