2011-11-28 14 views
5

Voglio usare MultiKeyMap da Apache Collection, perché ho bisogno di una HashMap con due chiavi e un valore. Per mettere elementi che fare questo:Metodo MultiKeyMap get

private MultiKeyMap multiKey = new MultiKeyMap(); 
multiKey.put("key1.1", "key2.1", "value1"); 

E per elemento get faccio questo:

String s = multiKey.get("key1.1"); 

ma la stringa s cames nulla ... Se io passo le due chiavi, come quello :

String s = multiKey.get("key1.1", "key2.1"); 

la stringa s cames con i valori valore1 ...

Come è possibile estendere la MultiKeyMap per ottenere il valore corretto quando passo solo uno dei due tasti?

+0

utilizzare una normale hashmap? http://stackoverflow.com/q/822322/106261 – NimChimpsky

+0

Yah, hai ragione ...;) – josecampos

risposta

4

Se hai bisogno di una sola chiave per ottenere un valore, hai una semplice vecchia HashMap.

private Map<String, String> map = new HashMap<>(); 

map.put("key1.1", "value1"); 
map.put("key2.1", "value1"); 

E per elemento get si può fare questo:

String s = map.get("key1.1"); // s == "value1" 

MultiKeyMap è necessaria quando devono essere forniti entrambi i tasti.

+0

Yah, hai ragione ...;) Per la prossima volta, ho bisogno di pensare fuori dagli schemi. .. – josecampos

5

Se si specifica un valore con due tasti, saranno necessari entrambi i tasti per recuperarlo. La funzione di hash non è progettata per restituire tutti i valori possibili associati a una sola delle due chiavi. Potrebbe essere necessario trovare una diversa struttura dati per farlo.

1

MultiKeyMap tratta di utilizzare tuple come chiavi, non di fare corrispondere un valore a più di una chiave. Usa una mappa normale e inserisci il tuo valore due volte, con chiavi diverse.

Una maggiore cautela è necessaria quando si rimuovono i valori. Quando rimuovi un valore per la prima chiave, vuoi rimuovere automaticamente altre chiavi con lo stesso valore? In tal caso, è necessario eseguire il loop su tutte le chiavi e rimuovere quelli con lo stesso valore a mano, il che potrebbe essere inefficiente o mantenere una sorta di mappa inversa per trovare rapidamente le chiavi per un valore specifico.

1

Sembra che semplicemente non sia necessario MultiKeyMap. Hai bisogno di una mappa regolare. Usandolo puoi associare lo stesso valore con tante chiavi quante ne vuoi.

Map<String, String> map = new HashMap<String, String>(); 
Object value = ..... 
map.put("key1", value); 
map.put("key2", value); 

.................. 

if(map.get("key1") == map.get("ke2")) { 
    System.out.println("the same value stored under 2 different keys!"); 
} 
0

Non si può, dal momento che non è il modo in cui funziona un MultiKeyMap. Metti il ​​valore con chiavi separate e cerca di ottenerlo con ciascun tasto alla volta.

0

Invece di che è possibile utilizzare i dati statura tavolo da guava.

0

Vorrei suggerire di creare una classe separata per più tasti:

public class Test { 

Map<Shape, Book> test1 = new HashMap<>(); 
Book book = new Book("A"); 
test1.put(Shape, book); 


private class Shape { 
    String id1; 
    String id2; 
public Shape(String id1, String id2) { 
    this.id1 = id1; 
    this.id2 = id2; 
} 
@Override 
public boolean equals(Object o) {//} 
@Override 
public int hashCode() {//} 
} 

} 
0

Ecco una semplice implementazione MultiKeyMap che ha lavorato per me.

import java.util.Collection; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Map; 
import java.util.Set; 
import java.util.UUID; 

public class MultiMap<K, V> implements Map<K, V> 
{ 
    private class MultiMapEntery implements java.util.Map.Entry<K, V> 
    { 
     private final K key; 
     private V value; 

     public MultiMapEntery(K key, V value) 
     { 
      this.key = key; 
      this.value = value; 
     } 
     @Override 
     public K getKey() 
     { 
      return key; 
     } 

     @Override 
     public V getValue() 
     { 
      return value; 
     } 

     @Override 
     public V setValue(V value) 
     { 
      V oldValue = this.value; 
      this.value = value; 
      return oldValue; 
     } 
    }; 

    private final Map<K, String> keyMap = new HashMap<K, String>(); 
    private final Map<String, Set<K>> inverseKeyMap = new HashMap<String, Set<K>>(); 
    private final Map<String, V> valueMap = new HashMap<String, V>(); 

    @Override 
    public void clear() 
    { 
     keyMap.clear(); 
     inverseKeyMap.clear(); 
     valueMap.clear(); 
    } 

    @Override 
    public boolean containsKey(Object key) 
    { 
     return keyMap.containsKey(key); 
    } 

    @Override 
    public boolean containsValue(Object value) 
    { 
     return valueMap.containsValue(value); 
    } 

    @Override 
    public Set<java.util.Map.Entry<K, V>> entrySet() 
    { 
     Set<java.util.Map.Entry<K, V>> entries = new HashSet<>(); 
     for(K key : keyMap.keySet()) 
     { 
      V value = valueMap.get(key); 
      entries.add(new MultiMapEntery(key, value)); 
     } 
     return entries; 
    } 

    @Override 
    public V get(Object key) 
    { 
     return valueMap.get(keyMap.get(key)); 
    } 

    @Override 
    public boolean isEmpty() 
    { 
     return valueMap.isEmpty(); 
    } 

    @Override 
    public Set<K> keySet() 
    { 
     return keyMap.keySet(); 
    } 

    @Override 
    public V put(K key, V value) 
    { 
     String id = keyMap.get(key); 
     if(id == null) 
     { 
      id = UUID.randomUUID().toString(); 
     } 
     keyMap.put(key, id); 
     Set<K> keys = inverseKeyMap.get(id); 
     if(keys == null) 
     { 
      keys = new HashSet<>(); 
     } 
     keys.add(key); 
     inverseKeyMap.put(id, keys); 
     valueMap.put(id, value); 
     return value; 
    } 

    public V put(Set<K> keys, V value) 
    { 
     String id = null; 
     for(K key : keys) 
     { 
      id = keyMap.get(key); 
      if(id != null) // one of the keys already exists 
      { 
       break; 
      } 
     } 

     if(id == null) 
     { 
      id = UUID.randomUUID().toString(); 
     } 

     for(K key : keys) 
     { 
      keyMap.put(key, id); 
     } 
     inverseKeyMap.put(id, keys); 
     valueMap.put(id, value); 
     return value; 
    } 

    @Override 
    public void putAll(Map<? extends K, ? extends V> map) 
    { 
     for(java.util.Map.Entry<? extends K, ? extends V> entry : map.entrySet()) 
     { 
      put(entry.getKey(), entry.getValue()); 
     } 
    } 

    @Override 
    public V remove(Object key) 
    { 
     String id = keyMap.get(key); 
     keyMap.remove(key); 
     Set<K> keys = inverseKeyMap.get(id); 
     keys.remove(key); 
     V value = valueMap.get(id); 
     if(keys.size() == 0) // it was the last key, now remove the value 
     { 
      valueMap.remove(id); 
     } 
     return value; 
    } 

    @Override 
    public int size() 
    { 
     return valueMap.size(); 
    } 

    @Override 
    public Collection<V> values() 
    { 
     return valueMap.values(); 
    } 

    public static void main(String[] args) 
    { 
     MultiMap<String, String> m = new MultiMap<>(); 
     m.put("a", "v1"); 
     Set<String> s = new HashSet<>(); 
     s.add("b"); 
     s.add("c"); 
     s.add("d"); 
     m.put(s, "v2"); 

     System.out.println("size:" + m.size()); 
     System.out.println("keys:" + m.keySet()); 
     System.out.println("values:" + m.values().toString()); 
     System.out.println("a:" + m.get("a")); 
     System.out.println("b:" + m.get("b")); 
     System.out.println("c:" + m.get("c")); 
     System.out.println("d:" + m.get("d")); 

     m.remove("a"); 

     System.out.println("size:" + m.size()); 
     System.out.println("keys:" + m.keySet()); 
     System.out.println("values:" + m.values().toString()); 
     System.out.println("a:" + m.get("a")); 
     System.out.println("b:" + m.get("b")); 
     System.out.println("c:" + m.get("c")); 
     System.out.println("d:" + m.get("d")); 

     s.add("a"); 
     m.put(s, "v3"); 

     System.out.println("size:" + m.size()); 
     System.out.println("keys:" + m.keySet()); 
     System.out.println("values:" + m.values().toString()); 

     System.out.println("a:" + m.get("a")); 
     System.out.println("b:" + m.get("b")); 
     System.out.println("c:" + m.get("c")); 
     System.out.println("d:" + m.get("d")); 
    } 
} 
Problemi correlati