2010-12-16 2 views
1

Мне нужно сопоставление из списка ключей к значению. Я знаю, что я мог бы написать свой собственный код, как это:Ищете реализацию «цепной карты» в Java

Map<Person, Map<Daytime, Map<Food, Integer>>> eaten = ...; 

Теперь я хочу, чтобы иметь некоторые get и put методы, подобные этим:

Integer numberOfEggsIAteInTheMorning = eaten.get(me, morning, scrambledEggs); 
eaten.put(me, evening, scrambledEggs, 1); 

Вы знаете, существующего класса, который имеет такого рода API? Я слишком ленив сам писать. ;)

ответ

1

Вы можете использовать org.apache.commons.collections.keyvalue.MultiKey для этого: Map<Multikey, Object>

1

Было бы сложно реализовать общую скованную карту.

Как будет выглядеть объявление класса? (Вы не можете иметь переменное число параметров типа.

class ChainedMap<K1..., V> 

Другим вариантом было бы иметь ChainedMapUtil класс, который выполняет положить/получить рекурсивно.

Вот пример рекурсивной получить. (Очень некрасиво решение, хотя я должен сказать.)

import java.util.*; 

public class Test { 

    public static Object chainedGet(Map<?, ?> map, Object... keys) { 

     Object k = keys[0]; 

     if (!map.containsKey(k)) return null; 

     if (keys.length == 1) return map.get(k); 

     Object[] tailKeys = Arrays.copyOfRange(keys, 1, keys.length); 
     return chainedGet((Map<?,?>) map.get(k), tailKeys);   
    } 

    public static void main(String[] arg) { 

     Map<String, String> m1 = new HashMap<String, String>(); 
     m1.put("ipsum", "dolor"); 

     Map<Integer, Map<String, String>> m2 = 
       new HashMap<Integer, Map<String, String>>(); 
     m2.put(17, m1); 

     Map<String, Map<Integer, Map<String, String>>> chained = 
      new HashMap<String, Map<Integer, Map<String, String>>>(); 
     chained.put("lorem", m2); 

     System.out.println(chainedGet(chained, "lorem", 17, "ipsum")); // dolor 
     System.out.println(chainedGet(chained, "lorem", 19, "ipsum")); // null 
    } 
} 
+0

Вы хотите сказать, будет или не будет? – 2010-12-16 11:21:46

+0

У вас может быть ChainedMap2 , ChainedMap3 и т. Д., Которые предоставили бы вам большинство полезных комбинаций, но общее решение будет включать в себя составные клавиши. – 2010-12-16 11:28:49

0

Если вы собираетесь написать свой собственный, я хотел бы предложить

eaten.increment(me, evening, scrambledEggs); 

Вы можете использовать (приращение TObjectIntHashMap поддерживает и настроить) Составной ключ

eaten.increment(Key.of(me, evening, scrambledEggs)); 

Вы можете даже не нужен пользовательский ключ.

eaten.increment(me + "," + evening + "," + scrambledEggs); 

Это довольно легко разлагаются ключ с расколом()

2

Если вы ищете более общий подход, и вы можете иметь более 2 или 3 «цепных шага», я бы предложил использовать несколько разных структурных подходов, а не придерживаться только базовых классов коллекций. У меня есть ощущение, что Composite Pattern может быть правильным выбором, если он правильно применяется.

EDIT: из примера просил

Полный пример будет несколько времени, поэтому позвольте мне просто объяснить мою идею с грязной Java/псевдокодом миксом (я даже не уверен, если я пропустил что нибудь!!!).Давайте рассмотрим у нас есть класс BaseMap:

abstract class BaseMap { 
    public abstract Object getValue(Object.. keys); 
    public abstract void putValue(Object value, Object.. keys); 
} 

Тогда мы могли бы иметь ObjectMap, который был бы «лист» нашей композитной структуры:

class ObjectsMap extends BaseMap { 
    private Map<Object, Object> map = new [...] 
    public Object getValue(Object.. keys) { 
     // assert that keys.length == 1 
     return map.get(keys[0]); 
    } 
    public void putValue(Object value, Object.. keys) { 
     // assert that keys.length = 1 
     map.put(keys[0], value); 
    } 
} 

И фактическая композит будет как таковой:

class CompositeMap extends BaseMap { 
    private Map<Object, BaseMap> compositeMaps = new [...] 
    public Object getValue(Object.. keys) { 
     // assert that keys.length > 1 
     return compositeMap.get(keys[0]).getValue(/* System.arrayCopy => subset of elements {keys_1, .. ,keys_max} */); 
    } 
    public void putValue(Object value, Object.. keys) { 
     // assert keys.length > 1 
     BaseMap newMap = null; 
     if (keys.length = 2) -> newMap = new ObjectsMap() 
     else newMap = new CompositeMap(); 
     newMap.putValue(value, /*subset of keys {keys_1, .. , keys_max}*/); 

    } 
} 
0

Я сделал карту, используя 3 ключа для развлечения. Возможно, вы сможете использовать его вместо использования прикованных карт:

public class ThreeKeyMap<K1,K2,K3,V>{ 

class wrap{ 
    K1 k1; 
    K2 k2; 
    K3 k3; 
    public wrap(K1 k1,K2 k2,K3 k3) { 
     this.k1=k1;this.k2=k2;this.k3=k3; 
    } 
    @Override 
    public boolean equals(Object arg0) { 
     // TODO Auto-generated method stub 
     wrap o=(wrap)arg0; 
    if(!this.k1.equals(o.k1)) 
     return false; 
    if(!this.k2.equals(o.k2)) 
     return false; 
    if(!this.k2.equals(o.k2)) 
     return false; 
    return true; 

    } 
    @Override 
    public int hashCode() { 
     int result=17; 
     result=37*result+k1.hashCode(); 
     result=37*result+k2.hashCode(); 
     result=37*result+k3.hashCode(); 
     return result; 
    } 
} 
HashMap<wrap,V> map=new HashMap<wrap, V>(); 

public V put(K1 k1,K2 k2,K3 k3,V arg1) { 
    return map.put(new wrap(k1,k2,k3), arg1); 
} 


public V get(Object k1,Object k2,Object k3) { 
    return map.get(new wrap((K1)k1,(K2)k2,(K3)k3)); 
} 

public static void main(String[] args) { 
    ThreeKeyMap<Integer,Integer,Integer,String> birthDay=new ThreeKeyMap<Integer, Integer, Integer, String>(); 
    birthDay.put(1, 1,1986,"Emil"); 
    birthDay.put(2,4,2009, "Ansih"); 
    birthDay.put(1, 1,1986,"Praveen"); 
    System.out.println(birthDay.get(1,1,1986)); 
} 
} 

UPDATE:

Как @Arturs LĪCIS suggested.I ищется в сети для составного шаблона, и я написал образец, используя it.I думаю, это composite..Please комментарий, если это не так.

класс Person: класс

public class Person { 
    private final String name; 
    private Map<Time, Food> map = new HashMap<Time, Food>(); 

    public Person(String name) { 
     this.name = name; 
    } 

    void addTimeFood(Time time, Food food) { 
     map.put(time, food); 
    } 

    public String getName() { 
     return name; 
    } 

    Food getFood(Time time) { 
     Food tmp = null; 
     return (tmp = map.get(time)) == null ? Food.NoFood : tmp; 
    } 
    // main to test the person class 
    public static void main(String[] args) { 
     Person p1 = new Person("Jack"); 
     p1.addTimeFood(Time.morning, Food.Bread); 
     p1.addTimeFood(Time.evening, Food.Chicken); 

     Person p2 = new Person("Jill"); 
     p2.addTimeFood(Time.morning, Food.Egg); 
     p2.addTimeFood(Time.evening, Food.Rice); 

     Map<String, Person> map = new HashMap<String, Person>(); 
     map.put(p1.getName(), p1); 
     map.put(p2.getName(), p2); 
     System.out.println(map.get("Jack").getFood(Time.evening)); 
    } 

    @Override 
    public String toString() { 
     StringBuilder b = new StringBuilder(); 
     b.append(name).append("\n"); 
     b.append(map); 
     return b.toString(); 
    } 
} 

Питание:

public enum Food { 
Rice, 
Egg, 
Chicken, 
Bread, 
NoFood; 
} 

Время Класс:

public enum Time { 
morning, 
evening, 
night 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^