View Javadoc

1   package cz.cuni.amis.utils.maps;
2   
3   import java.util.Collections;
4   import java.util.HashMap;
5   import java.util.Map;
6   import java.util.WeakHashMap;
7   
8   
9   /**
10   * Three-level hash map, where the PRIMARY_KEY maps are implemented using
11   * {@link WeakHashMap}.
12   * This means, that the PRIMARY_KEY maps, may be garbage collected unless there is a direct reference to the PRIMARY_KEY.
13   * @author srlok
14   *
15   * @param <PRIMARY_KEY>
16   * @param <SECONDARY_KEY>
17   * @param <TERTIARY_KEY> 
18   * @param <ITEM>
19   */
20  public class WeakHashTriMap<PRIMARY_KEY,SECONDARY_KEY,TERTIARY_KEY,ITEM>
21  	extends WeakHashMap<PRIMARY_KEY,Map<SECONDARY_KEY,Map<TERTIARY_KEY,ITEM>>> 
22  {
23  
24  	/**
25  	 * 
26  	 */
27  	private static final long serialVersionUID = 1L;
28  
29  	private int secondaryCapacity;
30  	private int tertiaryCapacity;
31  	
32  	/**
33  	 * Creates a WeakHashTriMap with default loadFactor(0.75) and default starting capacities (16,16,16)
34  	 */
35  	public WeakHashTriMap()
36  	{
37  		secondaryCapacity = 16;
38  		tertiaryCapacity = 16;
39  	}
40  	
41  	/**
42  	 * Creates a new WeakHashTriMap with the default loadFactor (0.75) for all levels and the provided starting capacties for different levels.
43  	 * @param primaryCapacity
44  	 * @param secondaryCapacity
45  	 * @param tertiaryCapacity
46  	 */
47  	public WeakHashTriMap( int primaryCapacity, int secondaryCapacity, int tertiaryCapacity)
48  	{
49  		super(primaryCapacity);
50  		this.secondaryCapacity = secondaryCapacity;
51  		this.tertiaryCapacity = tertiaryCapacity;
52  	}
53  	
54  	/**
55  	 * Returns a HashMap<SECONDARY_KEY,HashMap<TERTIARY_KEY,ITEM>>
56  	 * Never returns null, if the map under primary key doesn't exist, an empty one is added and returned.
57  	 * @param primaryKey
58  	 * @return
59  	 */
60  	@SuppressWarnings("unchecked")
61  	@Override
62  	public Map<SECONDARY_KEY, Map<TERTIARY_KEY,ITEM>> get(Object primaryKey)
63  	{
64  		Map<SECONDARY_KEY, Map<TERTIARY_KEY,ITEM>> result = super.get(primaryKey);
65  		if (result != null) { return result; };
66  		result = Collections.synchronizedMap( new HashMapMap<SECONDARY_KEY,TERTIARY_KEY,ITEM>(secondaryCapacity, tertiaryCapacity) );
67  		super.put( (PRIMARY_KEY)primaryKey,result);
68  		return result;
69  	}
70  	
71  	/**
72  	 * Returns the requested map, never returns null.
73  	 * If the map does not exist an empty map is created and returned.
74  	 * @param primaryKey
75  	 * @param secondaryKey
76  	 * @return
77  	 */
78  	public Map<TERTIARY_KEY,ITEM> get(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey)
79  	{
80  		Map<TERTIARY_KEY, ITEM> result = get(primaryKey).get(secondaryKey);
81  		if (result != null) { return result; };
82  		result = Collections.synchronizedMap( new HashMap<TERTIARY_KEY,ITEM>( tertiaryCapacity ));
83  		get(primaryKey).put(secondaryKey, result);
84  		return result;
85  	}
86  	
87  	/**
88  	 * Returns item specified, returns null if item does not appear in the map.
89  	 * @param primaryKey
90  	 * @param secondaryKey
91  	 * @param tertiaryKey
92  	 * @return
93  	 */
94  	public ITEM get(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey, TERTIARY_KEY tertiaryKey)
95  	{
96  		return get(primaryKey,secondaryKey).get(tertiaryKey);
97  	}
98  	
99  	/**
100 	 * Puts the item into the map.
101 	 * @param primaryKey
102 	 * @param secondaryKey
103 	 * @param tertiaryKey
104 	 * @param item
105 	 */
106 	public void put(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey, TERTIARY_KEY tertiaryKey, ITEM item)
107 	{
108 		get(primaryKey,secondaryKey).put(tertiaryKey, item);
109 	}
110 	
111 	/**
112 	 * Removes the requested map. If the map doesn't exist, returns an empty map.
113 	 */
114 	@Override
115 	public Map<SECONDARY_KEY, Map<TERTIARY_KEY,ITEM>> remove(Object primaryKey)
116 	{
117 		Map<SECONDARY_KEY, Map<TERTIARY_KEY,ITEM>> result = super.remove(primaryKey);
118 		if (result != null) { return result; };
119 		return Collections.synchronizedMap( new HashMapMap<SECONDARY_KEY, TERTIARY_KEY,ITEM>(secondaryCapacity, tertiaryCapacity) );
120 	}
121 	
122 	/**
123 	 * removes the map under primary and secondary key, if the map does not exist,
124 	 * the data structure is not changed and a new map is returned.
125 	 * @param primaryKey
126 	 * @param secondaryKey
127 	 * @return
128 	 */
129 	public Map<TERTIARY_KEY,ITEM> remove(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey)
130 	{
131 		Map<TERTIARY_KEY,ITEM> result = get(primaryKey).remove(secondaryKey);
132 		if ( result != null) { return result; };
133 		return Collections.synchronizedMap( new HashMap<TERTIARY_KEY, ITEM> (tertiaryCapacity));
134 	}
135 	
136 	/**
137 	 * Returns the item under specified keys and removes it from the map,
138 	 * returns null if item is not present in the map.
139 	 * @param primaryKey
140 	 * @param secondaryKey
141 	 * @param tertiaryKey
142 	 * @return
143 	 */
144 	public ITEM remove(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey, TERTIARY_KEY tertiaryKey)
145 	{
146 		return get(primaryKey,secondaryKey).remove(tertiaryKey);
147 	}
148 
149 }