2011-11-28 37 views
5

Quiero usar MultiKeyMap de Apache Collection, porque necesito un HashMap con dos claves y un valor. Para poner los elementos que hacer esto:MultiKeyMap get method

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

Y para el elemento get hago esto:

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

Pero la cadena s cames nula ... Si paso las dos llaves, al igual que :

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

la cadena s Cames con los valores valor1 ...

¿Cómo puedo extender el MultiKeyMap para obtener el valor correcto cuando paso solo una de las dos claves?

+0

utilizar un hashmap normal? http://stackoverflow.com/q/822322/106261 – NimChimpsky

+0

Yah, tienes razón ...;) – josecampos

Respuesta

4

Si solo necesita una clave para obtener un valor, tiene un HashMap antiguo.

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

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

Y para el elemento get se puede hacer esto:

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

MultiKeyMap es necesario cuando se deben proporcionar ambas teclas.

+0

Yah, tienes razón ...;) Para la próxima vez, necesito pensar fuera de la caja. .. – josecampos

5

Si especifica un valor con dos teclas, necesitará ambas claves para recuperarlo. La función hash no está diseñada para devolver todos los valores posibles que están asociados con solo una de las dos claves. Es posible que necesite encontrar una estructura de datos diferente para hacer esto.

1

MultiKeyMap se trata de usar tuplas como claves, no de hacer coincidir un valor con más de una clave. Usa un mapa normal y simplemente pon tu valor dos veces, con diferentes claves.

Se necesita más precaución al eliminar valores. Cuando elimina un valor para la primera clave, ¿desea eliminar automáticamente otras claves con el mismo valor? Si es así, debe recorrer todas las teclas y eliminarlas con el mismo valor a mano, lo que podría ser ineficiente, o mantener algún tipo de mapa inverso para encontrar rápidamente las claves para un valor específico.

1

Parece que simplemente no necesita MultiKeyMap. Necesitas un mapa regular Al usarlo, puede asociar el mismo valor con tantas teclas como desee.

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

No puede porque no es la forma en que funciona un MultiKeyMap. Coloque el valor con claves separadas y luego intente obtenerlo con cada clave a la vez.

0

En lugar de que se puede utilizar estatura datos de la tabla de guayaba.

0

sugeriría para crear una clase separada para varias claves:

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

Aquí es una sencilla aplicación MultiKeyMap que trabajó para mí.

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