¿Cómo insertar un "Par" o tamaño n en una colección de listas en lugar de componer HashMaps?

StackOverflow https://stackoverflow.com/questions/835359

Pregunta

Entonces, tengo una situación en la que necesito pasar tres valores a una cola serial de BlockingQueue:

(SelectableChannel, ComponentSocketBasis, Integer).

En realidad no es necesario que se asignen hash en absoluto, y usar un HashMap es ridículo, ya que siempre habrá una sola clave para cada entrada; estaría bien si estuvieran en algún tipo de conjunto ordenado. Sin embargo, por falta de una alternativa conocida, utilicé un HashMap en mi implementación y produje esta composición genérica ofuscada:

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

Esto parece realmente ridículo. Debo ser un terrible n00b. Seguramente hay una mejor manera de hacer esto que no requiere que descomponga la clave al recuperar los valores o desperdicie la complejidad algorítmica (teórica, en la práctica, siempre hinchada de Java :) en un cálculo hash inútil que no necesito porque tengo un espacio clave de 1 y ni siquiera quiero mapear relacionalmente las tres referencias, sino simplemente agruparlas. Con esta implementación, tengo que extraer los valores de esta manera:

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

Estoy bastante seguro de que todo ser capaz de razonar de forma sensible aquí probablemente piense que esta es una forma ridícula de hacerlo, así que la pregunta es: ¿cuál es la forma correcta? :) No puedo encontrar evidencia de un java.util.Pair o java.util.Triplet en ninguna parte.

Supongo que una forma ortodoxa (TM) sería hacer una clase o interfaz personalizada solo con el propósito de alojar este triplete, pero para una tarea tan pequeña en un sistema tan grande, esto parece absurdamente verboso e innecesario, aunque una vez más, eso es Java en sí.

Del mismo modo, quizás los valores se pueden poner en una ArrayList o un Vector o derivado de la misma, pero en Java esto no ofrece una forma más concisa de abordarlos de lo que obtengo de este HashMap aquí, aunque resuelve el problema de complejidad algorítmica, tal vez.

De vuelta en tierra Perl, simplemente haríamos esto usando una referencia de matriz como valor dentro de una matriz:

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

¿Cuál es el mejor equivalente en Java?

¿Fue útil?

Solución

¿Por qué no simplemente crear sus propias clases genéricas de pares o triples? ¡Casi todos los proyectos Java 5+ terminan teniendo en sus propias clases de utilidades!

Otros consejos

Usted dice que una clase personalizada para contener el triplete sería hinchada e innecesaria, pero esta es realmente la forma de hacerlo, así es como funciona el modelado orientado a objetos. Una clase personalizada es explícita y legible, y no requiere más recursos de tiempo de ejecución que una clase de titular genérico.

Java funcional tiene pares , trillizos , y tuplas hasta arity 8. También hay un tipo llamado HList para arity arbitraria. Entonces su tipo sería:

LinkedBlockingQueue<P3<SelectableChannel, ComponentSocketBasis, Integer>>

Esto es solo una biblioteca, así que suelta el frasco en tu classpath y listo.

Podría usar una ArrayList para almacenar los objetos, ya que sabe qué objeto estará en qué ubicación. Crear una nueva clase con los miembros SelectableChannel y ComponentSocketBasis para el probablemente sea mejor.

Si vas a hacer mucho este tipo de cosas, crear un par genérico o una tupla ahora te ahorrará mucho tiempo, pero si este es el único lugar donde lo vas a usar, entonces crear una nueva clase resultará en un código mucho más fácil de leer.

Cada vez que vea su nombre de clase en el código, sabrá exactamente para qué sirve, mientras que si solo ve su amalgamación genérica, podría ser más difícil para usted (u otra persona) entender lo que se está utilizando. .

Es una compensación entre el tiempo de programación y la legibilidad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top