001 package net.minecraft.util;
002
003 public class LongHashMap
004 {
005 /** the array of all elements in the hash */
006 private transient LongHashMapEntry[] hashArray = new LongHashMapEntry[16];
007
008 /** the number of elements in the hash array */
009 private transient int numHashElements;
010
011 /**
012 * the maximum amount of elements in the hash (probably 3/4 the size due to meh hashing function)
013 */
014 private int capacity = 12;
015
016 /**
017 * percent of the hasharray that can be used without hash colliding probably
018 */
019 private final float percentUseable = 0.75F;
020
021 /** count of times elements have been added/removed */
022 private transient volatile int modCount;
023
024 /**
025 * returns the hashed key given the original key
026 */
027 private static int getHashedKey(long par0)
028 {
029 return hash((int)(par0 ^ par0 >>> 32));
030 }
031
032 /**
033 * the hash function
034 */
035 private static int hash(int par0)
036 {
037 par0 ^= par0 >>> 20 ^ par0 >>> 12;
038 return par0 ^ par0 >>> 7 ^ par0 >>> 4;
039 }
040
041 /**
042 * gets the index in the hash given the array length and the hashed key
043 */
044 private static int getHashIndex(int par0, int par1)
045 {
046 return par0 & par1 - 1;
047 }
048
049 public int getNumHashElements()
050 {
051 return this.numHashElements;
052 }
053
054 /**
055 * get the value from the map given the key
056 */
057 public Object getValueByKey(long par1)
058 {
059 int var3 = getHashedKey(par1);
060
061 for (LongHashMapEntry var4 = this.hashArray[getHashIndex(var3, this.hashArray.length)]; var4 != null; var4 = var4.nextEntry)
062 {
063 if (var4.key == par1)
064 {
065 return var4.value;
066 }
067 }
068
069 return null;
070 }
071
072 public boolean containsItem(long par1)
073 {
074 return this.getEntry(par1) != null;
075 }
076
077 final LongHashMapEntry getEntry(long par1)
078 {
079 int var3 = getHashedKey(par1);
080
081 for (LongHashMapEntry var4 = this.hashArray[getHashIndex(var3, this.hashArray.length)]; var4 != null; var4 = var4.nextEntry)
082 {
083 if (var4.key == par1)
084 {
085 return var4;
086 }
087 }
088
089 return null;
090 }
091
092 /**
093 * Add a key-value pair.
094 */
095 public void add(long par1, Object par3Obj)
096 {
097 int var4 = getHashedKey(par1);
098 int var5 = getHashIndex(var4, this.hashArray.length);
099
100 for (LongHashMapEntry var6 = this.hashArray[var5]; var6 != null; var6 = var6.nextEntry)
101 {
102 if (var6.key == par1)
103 {
104 var6.value = par3Obj;
105 return;
106 }
107 }
108
109 ++this.modCount;
110 this.createKey(var4, par1, par3Obj, var5);
111 }
112
113 /**
114 * resizes the table
115 */
116 private void resizeTable(int par1)
117 {
118 LongHashMapEntry[] var2 = this.hashArray;
119 int var3 = var2.length;
120
121 if (var3 == 1073741824)
122 {
123 this.capacity = Integer.MAX_VALUE;
124 }
125 else
126 {
127 LongHashMapEntry[] var4 = new LongHashMapEntry[par1];
128 this.copyHashTableTo(var4);
129 this.hashArray = var4;
130 this.capacity = (int)((float)par1 * this.percentUseable);
131 }
132 }
133
134 /**
135 * copies the hash table to the specified array
136 */
137 private void copyHashTableTo(LongHashMapEntry[] par1ArrayOfLongHashMapEntry)
138 {
139 LongHashMapEntry[] var2 = this.hashArray;
140 int var3 = par1ArrayOfLongHashMapEntry.length;
141
142 for (int var4 = 0; var4 < var2.length; ++var4)
143 {
144 LongHashMapEntry var5 = var2[var4];
145
146 if (var5 != null)
147 {
148 var2[var4] = null;
149 LongHashMapEntry var6;
150
151 do
152 {
153 var6 = var5.nextEntry;
154 int var7 = getHashIndex(var5.hash, var3);
155 var5.nextEntry = par1ArrayOfLongHashMapEntry[var7];
156 par1ArrayOfLongHashMapEntry[var7] = var5;
157 var5 = var6;
158 }
159 while (var6 != null);
160 }
161 }
162 }
163
164 /**
165 * calls the removeKey method and returns removed object
166 */
167 public Object remove(long par1)
168 {
169 LongHashMapEntry var3 = this.removeKey(par1);
170 return var3 == null ? null : var3.value;
171 }
172
173 /**
174 * removes the key from the hash linked list
175 */
176 final LongHashMapEntry removeKey(long par1)
177 {
178 int var3 = getHashedKey(par1);
179 int var4 = getHashIndex(var3, this.hashArray.length);
180 LongHashMapEntry var5 = this.hashArray[var4];
181 LongHashMapEntry var6;
182 LongHashMapEntry var7;
183
184 for (var6 = var5; var6 != null; var6 = var7)
185 {
186 var7 = var6.nextEntry;
187
188 if (var6.key == par1)
189 {
190 ++this.modCount;
191 --this.numHashElements;
192
193 if (var5 == var6)
194 {
195 this.hashArray[var4] = var7;
196 }
197 else
198 {
199 var5.nextEntry = var7;
200 }
201
202 return var6;
203 }
204
205 var5 = var6;
206 }
207
208 return var6;
209 }
210
211 /**
212 * creates the key in the hash table
213 */
214 private void createKey(int par1, long par2, Object par4Obj, int par5)
215 {
216 LongHashMapEntry var6 = this.hashArray[par5];
217 this.hashArray[par5] = new LongHashMapEntry(par1, par2, par4Obj, var6);
218
219 if (this.numHashElements++ >= this.capacity)
220 {
221 this.resizeTable(2 * this.hashArray.length);
222 }
223 }
224
225 /**
226 * public method to get the hashed key(hashCode)
227 */
228 static int getHashCode(long par0)
229 {
230 return getHashedKey(par0);
231 }
232 }