Come inserire un & # 8220; Accoppia & # 8221; o dimensione n in una raccolta di elenchi invece di comporre HashMaps?

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

Domanda

Quindi, ho una situazione in cui devo passare tre valori in una coda BlockingQueue seriale:

(SelectableChannel, ComponentSocketBasis, Integer).

In realtà non devono assolutamente essere mappati con l'hash, e usare una HashMap è ridicolo in quanto ci sarà sempre una sola chiave per ogni voce; andrebbe bene se fossero solo in una sorta di set ordinato. Per mancanza di un'alternativa nota, tuttavia, ho usato una HashMap nella mia implementazione e prodotto questa composizione generica offuscata:

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

Questo sembra davvero ridicolo. Devo essere un terribile n00b. Sicuramente c'è un modo migliore per farlo che non richiede che io decomponga la chiave quando recuperi i valori o sprechi la complessità algoritmica (teorica - in pratica, Java è sempre gonfia :) su un inutile calcolo dell'hash che non mi serve perché ho uno spazio chiave di 1 e non voglio nemmeno mappare relazionalmente i tre riferimenti, ma semplicemente raggrupparli? Con questa implementazione, devo estrarre i valori in questo modo:

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

Sono abbastanza sicuro che ogni essere capace di ragione senziente qui probabilmente pensa che questo sia un modo ridicolo per farlo, quindi la domanda è: qual è la strada giusta? :) Non riesco a trovare prove di java.util.Pair o java.util.Triplet da nessuna parte.

Suppongo che un modo ortodosso (TM) sarebbe quello di fare una classe o un'interfaccia personalizzata solo allo scopo di ospitare questa tripletta, ma per un compito così piccolo in un sistema così grande sembra assurdamente prolisso e inutile, sebbene, poi di nuovo, è Java stesso.

Allo stesso modo, forse i valori possono essere inseriti in una ArrayList o in un Vector o in una sua derivata, ma in Java questo non produce un modo più conciso di indirizzarli di quanto non ne esca da questa HashMap qui, sebbene risolve forse il problema della complessità algoritmica.

Tornando nella terra del Perl, lo faremmo semplicemente usando un riferimento di array come valore all'interno di un array:

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

Qual è il miglior equivalente in Java?

È stato utile?

Soluzione

Perché non creare semplicemente le tue classi Pair o Triple generiche? Praticamente ogni progetto Java 5+ finisce per averli nelle proprie classi util!

Altri suggerimenti

Dici che una classe personalizzata per contenere la tripletta sarebbe gonfia e inutile, ma questo è davvero il modo di farlo, ecco come funziona la modellazione orientata agli oggetti. Una classe personalizzata è esplicita e leggibile e non occupa più risorse di runtime di una classe di titolari generica.

Java funzionale ha coppie , terzine e tupla fino a arity 8. C'è anche un tipo chiamato HList per arbitrarietà. Quindi il tuo tipo sarebbe:

LinkedBlockingQueue<P3<SelectableChannel, ComponentSocketBasis, Integer>>

Questa è solo una libreria, quindi lascia cadere il vaso nel tuo percorso di classe e sei a posto.

Potresti semplicemente usare una ArrayList per memorizzare gli oggetti, poiché sai quale oggetto sarà in quale posizione. Creare una nuova classe con i membri SelectableChannel e ComponentSocketBasis per probabilmente sarebbe meglio.

Se stai facendo molto questo genere di cose, creare una coppia generica o una tupla ora ti farà risparmiare un sacco di tempo, ma se questo è l'unico posto dove lo utilizzerai, allora la creazione di una nuova classe renderà il codice molto più semplice da leggere.

Ogni volta che vedi il tuo nome di classe nel codice, saprai esattamente a cosa serve, mentre se vedi solo la tua fusione generica, potrebbe essere più difficile per te (o per qualcun altro) capire a cosa serve .

È un compromesso tra tempo di programmazione e leggibilità.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top