1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.onemind.commons.java.datastructure;
22
23 import java.util.HashMap;
24 /***
25 * A simple bi-directional map. It uses another map to store the inverse
26 * of this map. The key has to be unique in key space and the value need to
27 * be unique in the value space so that the value can be resolved to the key correctly.
28 * This class is not thread safe.
29 * @author TiongHiang Lee (thlee@onemindsoft.org)
30 * @version $Id: BiMap.java,v 1.1 2004/09/29 02:45:35 thlee Exp $ $Name: $
31 */
32 public class BiMap extends HashMap
33 {
34
35 /*** the inverse **/
36 private final BiMap _inverse;
37
38 /***
39 * Constructor
40 */
41 public BiMap()
42 {
43 _inverse = new BiMap(this);
44 }
45
46 /***
47 * Constructor
48 * @param map the inverse
49 */
50 private BiMap(BiMap inverse)
51 {
52 _inverse = inverse;
53 }
54
55 /***
56 * Get the inverse bimap
57 * @return the bimap
58 */
59 public BiMap getInverse()
60 {
61 return _inverse;
62 }
63
64 /***
65 * {@inheritDoc}
66 */
67 public void clear()
68 {
69 super.clear();
70 _inverse.clear();
71 }
72
73 /***
74 * {@inheritDoc}
75 */
76 public Object put(Object key, Object value)
77 {
78
79 if (containsKey(key))
80 {
81 if (_inverse.containsKey(value))
82 {
83 Object v = get(key);
84 boolean sameValue = (v == null) ? v == value : v.equals(value);
85 if (!sameValue)
86 {
87 throw new IllegalArgumentException("Value " + value + " exists in inverse");
88 }
89 }
90 } else
91 {
92 if (_inverse.containsKey(value))
93 {
94 throw new IllegalArgumentException("Value " + value + " exists in inverse");
95 }
96 }
97
98 remove(key);
99 _inverse.rawPut(value, key);
100 return rawPut(key, value);
101 }
102
103 /***
104 * Put the key value association with super.put()
105 * @param key the key
106 * @param value the value
107 */
108 private Object rawPut(Object key, Object value)
109 {
110 return super.put(key, value);
111 }
112
113 /***
114 * Remove the key
115 * @param key the key
116 * @return the value by super.remove();
117 */
118 private Object rawRemove(Object key)
119 {
120 return super.remove(key);
121 }
122
123 /***
124 * {@inheritDoc}
125 */
126 public Object remove(Object key)
127 {
128 if (containsKey(key))
129 {
130 return _inverse.rawRemove(rawRemove(key));
131 } else
132 {
133 return null;
134 }
135 }
136 }