1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.multimap.impl;
25
26 import java.util.Map;
27
28 import org.dishevelled.multimap.TernaryKey;
29 import org.dishevelled.multimap.TernaryKeyMap;
30
31
32
33
34
35
36
37
38
39
40 public final class HashedTernaryKeyMap<K1, K2, K3, V>
41 extends AbstractHashedMap<TernaryKey<K1, K2, K3>, V>
42 implements TernaryKeyMap<K1, K2, K3, V>
43 {
44
45
46
47
48 public HashedTernaryKeyMap()
49 {
50 super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
51 }
52
53
54
55
56
57
58
59
60
61 public HashedTernaryKeyMap(final int initialCapacity,
62 final float loadFactor,
63 final int threshold)
64 {
65 super(initialCapacity, loadFactor, threshold);
66 }
67
68
69
70
71
72
73
74 public HashedTernaryKeyMap(final Map<? extends TernaryKey<K1, K2, K3>, ? extends V> map)
75 {
76 super(map);
77 }
78
79
80
81
82
83
84
85
86
87
88 private int hash(final K1 key1, final K2 key2, final K3 key3)
89 {
90 int h = 0;
91 if (key1 != null)
92 {
93 h ^= key1.hashCode();
94 }
95 if (key2 != null)
96 {
97 h ^= key2.hashCode();
98 }
99 if (key3 != null)
100 {
101 h ^= key3.hashCode();
102 }
103 h += ~(h << 9);
104 h ^= (h >>> 14);
105 h += (h << 4);
106 h ^= (h >>> 10);
107 return h;
108 }
109
110
111
112
113
114
115
116
117
118
119 private boolean isEqualKey(final HashEntry<TernaryKey<K1, K2, K3>, V> entry,
120 final K1 key1,
121 final K2 key2,
122 final K3 key3)
123 {
124 TernaryKey<K1, K2, K3> key = entry.getKey();
125 return (key1 == null ? key.getFirstKey() == null : key1.equals(key.getFirstKey()))
126 && (key2 == null ? key.getSecondKey() == null : key2.equals(key.getSecondKey()))
127 && (key3 == null ? key.getThirdKey() == null : key3.equals(key.getThirdKey()));
128 }
129
130 @Override
131 public boolean containsKey(final K1 key1, final K2 key2, final K3 key3)
132 {
133 int hashCode = hash(key1, key2, key3);
134 HashEntry<TernaryKey<K1, K2, K3>, V> entry = data[hashIndex(hashCode, data.length)];
135 while (entry != null)
136 {
137 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3))
138 {
139 return true;
140 }
141 entry = entry.next;
142 }
143 return false;
144 }
145
146 @Override
147 public V get(final K1 key1, final K2 key2, final K3 key3)
148 {
149 int hashCode = hash(key1, key2, key3);
150 HashEntry<TernaryKey<K1, K2, K3>, V> entry = data[hashIndex(hashCode, data.length)];
151 while (entry != null)
152 {
153 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3))
154 {
155 return entry.getValue();
156 }
157 entry = entry.next;
158 }
159 return null;
160 }
161
162 @Override
163 public V put(final K1 key1, final K2 key2, final K3 key3, final V value)
164 {
165 int hashCode = hash(key1, key2, key3);
166 int index = hashIndex(hashCode, data.length);
167 HashEntry<TernaryKey<K1, K2, K3>, V> entry = data[index];
168 while (entry != null)
169 {
170 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3))
171 {
172 V oldValue = entry.getValue();
173 updateEntry(entry, value);
174 return oldValue;
175 }
176 entry = entry.next;
177 }
178 addMapping(index, hashCode, new TernaryKey<K1, K2, K3>(key1, key2, key3), value);
179 return null;
180 }
181
182 @Override
183 public V put(final TernaryKey<K1, K2, K3> key, final V value)
184 {
185 if (key == null)
186 {
187 throw new NullPointerException("key must not be null");
188 }
189 return super.put(key, value);
190 }
191
192 @Override
193 public V removeKey(final K1 key1, final K2 key2, final K3 key3)
194 {
195 int hashCode = hash(key1, key2, key3);
196 int index = hashIndex(hashCode, data.length);
197 HashEntry<TernaryKey<K1, K2, K3>, V> entry = data[index];
198 HashEntry<TernaryKey<K1, K2, K3>, V> previous = null;
199 while (entry != null)
200 {
201 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3))
202 {
203 V oldValue = entry.getValue();
204 removeMapping(entry, index, previous);
205 return oldValue;
206 }
207 previous = entry;
208 entry = entry.next;
209 }
210 return null;
211 }
212 }