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