2013-03-21 17 views
5

Ho bisogno di una mappa in cui la mia chiave dovrebbe essere basata su 3 colonne, ad esempio C1, C2, C3. C1 ha la priorità più alta. C2 ha uno in meno di C1 e C3 ha uno in meno di C2.Java Map con le chiavi di 3 colonne

Come si crea la chiave nella mappa in modo tale che se qualcuno richiede informazioni su C1, dovrei poter fornire tutti i valori che ha C1. Devo anche essere in grado di restituire tutti i valori se richiesto per C1 & C2

+4

Puoi mostrarci alcuni casi di test? Qual è il tuo input e il tuo output? –

+2

La domanda non è chiara .... – AmitG

+0

Questo non è un problema standard. Consente di affrontare questo problema specifico dello scenario corrente per il tuo utilizzo. Puoi dire per favore qual è il tipo di dati di C1, C2 e C3? Se sono numeri interi, quale sarebbe la gamma di essi? – Saurabh

risposta

2

È possibile utilizzare la stessa strategia indici multicolonna in database, se le colonne chiave possono essere ordinati (ad esempio, in Java, hanno bisogno di essere Comparable) e può facilmente definire i valori massimi e minimi per tutti tranne il primo.

Un esempio con colonne interi:

public class Key implements Comparable<Key> { 
    int c1, c2, c3; 

    private static final int c2_min = Integer.MIN_VALUE; 
    private static final int c2_max = Integer.MAX_VALUE; 
    private static final int c3_min = Integer.MIN_VALUE; 
    private static final int c3_max = Integer.MAX_VALUE; 

    @Override 
    public int compareTo(Key o) { 
     if (c1!=o.c1) return Integer.compare(c1, o.c1); 
     if (c2!=o.c2) return Integer.compare(c2, o.c2); 
     return Integer.compare(c3, o.c3); 
    } 

    // constructor, equals, ... 

} 

e quindi è possibile ottenere tutte le voci per qualche valore k1 in c1 simili:

map.subMap(new Key(k1, Key.c2_min, 0), new Key(k1, Key.c2_max, 0)); 

Analogamente, utilizzando i primi due colonne:

map.subMap(new Key(k1, k2, Key.c3_min), new Key(k1, k2, Key.c3_max)); 
+0

Grazie, ho una domanda il mio tipo è byte []. Come definire il valore MAX e MIN – Avinash

+0

Assumendo un [comparatore di byte] (http://stackoverflow.com/questions/5108091/java-comparator-for-byte-array-lexicographic), è possibile utilizzare 'MIN = new byte [ 0] '. Per 'MAX', se hai una dimensione massima dell'array, usalo e inizializza tutti gli elementi con' Byte.MAX_VALUE'. Altrimenti, devi scegliere qualche istanza (definita come 'static final') e controllarla esplicitamente in' compareTo' con '=='. Infine, a seconda dell'applicazione, 'null' potrebbe anche funzionare come valore massimo considerandolo esplicitamente in' compareTo'. – jop

0

Per "priorità", presumo tu intenda ciò che di solito viene definito come chiave primaria, secondaria e terziaria.

Se sono tutti campi stringa, concatenarli in un'unica stringa e utilizzarli come chiave. Nel tuo caso, la chiave è C1 + C2 + C3 (dove "+" si riferisce alla concatenazione di stringhe).

+0

ma come si recupereranno i valori solo corrispondenti a C1 o solo a C1 e C2? – Saurabh

2

Utilizzare tre mappe.

One Map<C1, V> and one Map<C2, V> and one Map<C3, V>. 

È possibile disporre le tre mappe in una classe e implementare il metodo.

0

Una mappa restituirà sempre un solo valore per una chiave. Non puoi farlo restituire più valori in base al contenuto delle tue classi chiave.

Il modo semplice è mantenere una mappa separata per ogni tipo di chiave e restituire i risultati appropriati in base alla chiave passata.

0

Un indice a tre livelli in cui una chiave di livello superiore può essere utilizzata per accedere a tutti i tasti e gli oggetti di livello inferiore richiede una mappa a tre livelli.

class ThreeLevelMap<K1,K2,K3,V> 
{ 
    private Map<K1,Map<K2,Map<K3,V>>> store = new HashMap<K,Map<K2,Map<K3,V>>>(); 
    ... 
    public V put(K1 key1, K2 key2, K3 key3, V value) { ... } 
    public V get(K1 key1, K2 key2, K3 key3) { ... } 

    public static class TLMEntry<K1,K2,K3,V> 
    { 
    ... 
    } 
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1, K2 key2) { ... } 
    public Collection<TLMEntry<K1,K2,K3,V>> get(K1 key1) { ... } 
} 

Questo è uno scheletro di base ma dovrebbe farti andare nella giusta direzione.

0

Questo sembra più un problema di database. Se si dispone di un database con una tabella strutturata come:

CREATE TABLE MyMap (
    id IDENTITY PRIMARY KEY, 
    c1 int, -- Change data types as needed. 
    c2 int, 
    c3 int, 
    v int); 

quindi si dovrebbe semplicemente emettere dichiarazioni SELECT contro di esso. Potresti voler utilizzare uno qualsiasi dei database Java in memoria.

Se non si vuole fare questo, si potrebbe fare l'equivalente puramente in Java funzionalmente scrivendo un contenitore di classe valore di classe:

class Cdata { 
    private int c1; 
    private int c2; 
    private int c3; 
    private int v; 
    // Constructors and getters elided. 
    public boolean match(int c1) { 
     return this.c1 == c1; 
    } 
    public boolean match(int c1, int c2) { 
     return match(c1) && this.c2 == c2; 
    } 
    public boolean match(int c1, int c2, int c3) { 
     return match(c1, c2) && this.c3 == c3; 
    } 
} 

quindi creare un elenco e utilizzare una libreria di programmazione funzionale con filtro metodi. Oppure, aspetta Java 8 lambda. L'utilizzo di Map<Integer, Map<Integer, Map<Integer, Integer>>>> è troppo confuso.

0

È possibile utilizzare TreeMap per raggiungere il vostro caso. Sto presupponendo il seguente: per i tre colonne mappano 3 crescenti valori interi esempio

C1 = 1, C2 = 2, C3 = 3

dove C1 = 1 è la priorità più alta e C2 = 2 è il prossimo in linea e così via.

Nota: le chiavi non devono sempre essere numeri interi, è possibile utilizzare qualsiasi tipo se si fornisce l'appropriato Comparator al numero TreeMap.

Con questo in luogo, si potrebbe fare qualcosa di simile:

TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>(); 
treeMap.put(1, "One"); 
treeMap.put(2, "two"); 
treeMap.put(3, "three"); 

List<String> list = getMappedValues(treeMap, 1);// returns One, Two, Three 
//List<String> list = getMappedValues(treeMap, 2);// returns Two, Three 
//List<String> list = getMappedValues(treeMap, 3);// returns Three 
//List<String> list = getMappedValues(treeMap, 4);// returns null 
if(list != null){ 
    //do something with the list of values 
} 

private static List<String> getMappedValues(TreeMap<Integer, String> map, Integer key) { 
    Entry<Integer, String> e = map.ceilingEntry(key); 
    if(e == null){ 
     return null; 
    } 
    List<String> list = new ArrayList<String>(); 
    while(e != null){ 
     list.add(e.getValue()); 
     key = e.getKey(); 
     e = map.higherEntry(key); 
    } 
    return list; 
} 
0

private class C { 

    public C() { 
     Map <Object ,String> ObjectC =new HashMap<Object, String>(); 
    } 
} 

private class B { 

    public B() { 
     Map <Object ,C> ObjectB =new HashMap<Object, C>(); 
    } 
} 

private class A { 

    public A() { 
     Map <Object ,B> ObjectA =new HashMap<Object, B>(); 
    } 
} 

quindi questo potrebbe promettere una bella struttura per la quale non è necessario lavorare di più ulteriormente come è possibile ottenere tutte il contenuto di un

MapVar.ObjectA.get(C1); 

se entrambi C1, C2 sono dati È possibile chiamare

MapVar.ObjectA.get(C1).ObjectB.get(C2); 

se entrambi C1, C2, C3 sono dati È possibile chiamare

MapVar.ObjectA.get(C1).ObjectB.get(C2).ObjectC.get(C3);; 

Quindi è possibile semplicemente scorrere la mappa e ottenere valori.

Problemi correlati