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