PageRenderTime 1379ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/saxonB/net/sf/saxon/sort/IntHashMap.java

https://bitbucket.org/dmwelch/phdxnat_pipeline
Java | 382 lines | 206 code | 47 blank | 129 comment | 44 complexity | 9bf59eb23d7f80fac25d6846fc4b9cc7 MD5 | raw file
  1. package net.sf.saxon.sort;
  2. import java.io.Serializable;
  3. import java.util.Iterator;
  4. /**
  5. * A hash table that maps int keys to Object values.
  6. *
  7. * @author Dave Hale, Landmark Graphics
  8. * @author Dominique Devienne
  9. * @author Michael Kay: retrofitted to JDK 1.4, added iterator(), modified to disallow null values
  10. */
  11. public class IntHashMap implements Serializable {
  12. /**
  13. * Initializes a map with a capacity of 8 and a load factor of 0,25.
  14. */
  15. public IntHashMap() {
  16. this(8, 0.25);
  17. }
  18. /**
  19. * Initializes a map with the given capacity and a load factor of 0,25.
  20. *
  21. * @param capacity the initial capacity.
  22. */
  23. public IntHashMap(int capacity) {
  24. this(capacity, 0.25);
  25. }
  26. /**
  27. * Constructs a new map with initial capacity, and load factor.
  28. * <p/>
  29. * The capacity is the number of keys that can be mapped without resizing
  30. * the arrays in which keys and values are stored. For efficiency, only
  31. * a fraction of the elements in those arrays are used. That fraction is
  32. * the specified load factor. The initial length of the arrays equals the
  33. * smallest power of two not less than the ratio capacity/factor. The
  34. * capacity of the map is increased, as necessary. The maximum number
  35. * of keys that can be mapped is 2^30.
  36. *
  37. * @param capacity the initial capacity.
  38. * @param factor the load factor.
  39. */
  40. public IntHashMap(int capacity, double factor) {
  41. _factor = factor;
  42. setCapacity(capacity);
  43. }
  44. /**
  45. * Clears the map.
  46. */
  47. public void clear() {
  48. _n = 0;
  49. for (int i = 0; i < _nmax; ++i) {
  50. //_filled[i] = false;
  51. _value[i] = null;
  52. }
  53. }
  54. /**
  55. * Finds a key in the map.
  56. *
  57. * @param key Key
  58. * @return true if the key is mapped
  59. */
  60. // public boolean find(int key) {
  61. // return _filled[indexOf(key)] ? true : false;
  62. // }
  63. /**
  64. * Gets the value for this key.
  65. *
  66. * @param key Key
  67. * @return the value, null if not found.
  68. */
  69. public Object get(int key) {
  70. // int i = indexOf(key);
  71. // return _filled[i] ? _value[i] : null;
  72. return _value[indexOf(key)];
  73. }
  74. /**
  75. * Gets the size of the map.
  76. *
  77. * @return the size (the number of entries in the map)
  78. */
  79. public int size() {
  80. return _n;
  81. }
  82. /**
  83. * Removes a key from the map.
  84. *
  85. * @param key Key to remove
  86. * @return true if the value was removed
  87. */
  88. public boolean remove(int key) {
  89. // Knuth, v. 3, 527, Algorithm R.
  90. int i = indexOf(key);
  91. //if (!_filled[i]) {
  92. if (_value[i] == null) {
  93. return false;
  94. }
  95. --_n;
  96. for (; ;) {
  97. //_filled[i] = false;
  98. _value[i] = null;
  99. int j = i;
  100. int r;
  101. do {
  102. i = (i - 1) & _mask;
  103. //if (!_filled[i]) {
  104. if (_value[i] == null) {
  105. return true;
  106. }
  107. r = hash(_key[i]);
  108. } while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r));
  109. _key[j] = _key[i];
  110. _value[j] = _value[i];
  111. //_filled[j] = _filled[i];
  112. }
  113. }
  114. /**
  115. * Adds a key-value pair to the map.
  116. *
  117. * @param key Key
  118. * @param value Value
  119. * @return the value that was previously associated with the key, or null if there was no previous value
  120. */
  121. public Object put(int key, Object value) {
  122. if (value == null) {
  123. throw new NullPointerException("IntHashMap does not allow null values");
  124. }
  125. int i = indexOf(key);
  126. Object old = _value[i];
  127. if (old != null) {
  128. _value[i] = value;
  129. } else {
  130. _key[i] = key;
  131. _value[i] = value;
  132. grow();
  133. }
  134. return old;
  135. }
  136. ///////////////////////////////////////////////////////////////////////////
  137. // private
  138. private static final int NBIT = 30; // NMAX = 2^NBIT
  139. private static final int NMAX = 1 << NBIT; // maximum number of keys mapped
  140. private double _factor; // 0.0 <= _factor <= 1.0
  141. private int _nmax; // 0 <= _nmax = 2^nbit <= 2^NBIT = NMAX
  142. private int _n; // 0 <= _n <= _nmax <= NMAX
  143. private int _nlo; // _nmax*_factor (_n<=_nlo, if possible)
  144. private int _nhi; // NMAX*_factor (_n< _nhi, if possible)
  145. private int _shift; // _shift = 1 + NBIT - nbit (see function hash() below)
  146. private int _mask; // _mask = _nmax - 1
  147. private int[] _key; // array[_nmax] of keys
  148. //@SuppressWarnings(value = {"unchecked"})
  149. private Object[] _value; // array[_nmax] of values
  150. //private boolean[] _filled; // _filled[i]==true iff _key[i] is mapped
  151. private int hash(int key) {
  152. // Knuth, v. 3, 509-510. Randomize the 31 low-order bits of c*key
  153. // and return the highest nbits (where nbits <= 30) bits of these.
  154. // The constant c = 1327217885 approximates 2^31 * (sqrt(5)-1)/2.
  155. return ((1327217885 * key) >> _shift) & _mask;
  156. }
  157. private int indexOf(int key) {
  158. int i = hash(key);
  159. //while (_filled[i]) {
  160. while (_value[i] != null) {
  161. if (_key[i] == key) {
  162. return i;
  163. }
  164. i = (i - 1) & _mask;
  165. }
  166. return i;
  167. }
  168. private void grow() {
  169. ++_n;
  170. if (_n > NMAX) {
  171. throw new RuntimeException("number of keys mapped exceeds " + NMAX);
  172. }
  173. if (_nlo < _n && _n <= _nhi) {
  174. setCapacity(_n);
  175. }
  176. }
  177. private void setCapacity(int capacity) {
  178. if (capacity < _n) {
  179. capacity = _n;
  180. }
  181. double factor = (_factor < 0.01) ? 0.01 : (_factor > 0.99) ? 0.99 : _factor;
  182. int nbit, nmax;
  183. for (nbit = 1, nmax = 2; nmax * factor < capacity && nmax < NMAX; ++nbit, nmax *= 2) {
  184. ;
  185. }
  186. int nold = _nmax;
  187. if (nmax == nold) {
  188. return;
  189. }
  190. _nmax = nmax;
  191. _nlo = (int)(nmax * factor);
  192. _nhi = (int)(NMAX * factor);
  193. _shift = 1 + NBIT - nbit;
  194. _mask = nmax - 1;
  195. int[] key = _key;
  196. Object[] value = _value;
  197. //boolean[] filled = _filled;
  198. _n = 0;
  199. _key = new int[nmax];
  200. // semantically equivalent to _value = new V[nmax]
  201. _value = new Object[nmax];
  202. //_filled = new boolean[nmax];
  203. if (key != null) {
  204. for (int i = 0; i < nold; ++i) {
  205. //if (filled[i]) {
  206. if (value[i] != null) {
  207. put(key[i], value[i]);
  208. }
  209. }
  210. }
  211. }
  212. /**
  213. * Get an iterator over the keys
  214. */
  215. public IntIterator keyIterator() {
  216. return new IntHashMapKeyIterator();
  217. }
  218. /**
  219. * Get an iterator over the values
  220. */
  221. public Iterator valueIterator() {
  222. return new IntHashMapValueIterator();
  223. }
  224. /**
  225. * Create a copy of the IntHashMap
  226. */
  227. public IntHashMap copy() {
  228. IntHashMap n = new IntHashMap(size());
  229. IntIterator it = keyIterator();
  230. while (it.hasNext()) {
  231. int k = it.next();
  232. n.put(k, get(k));
  233. }
  234. return n;
  235. }
  236. /**
  237. * Diagnostic display of contents
  238. */
  239. public void display() {
  240. IntIterator iter = new IntHashMapKeyIterator();
  241. while (iter.hasNext()) {
  242. int key = iter.next();
  243. Object value = get(key);
  244. System.err.println(key + " -> " + value.toString());
  245. }
  246. }
  247. /**
  248. * Iterator over keys
  249. */
  250. private class IntHashMapKeyIterator implements IntIterator, Serializable {
  251. private int i = 0;
  252. public IntHashMapKeyIterator() {
  253. i = 0;
  254. }
  255. public boolean hasNext() {
  256. while (i < _key.length) {
  257. if (_value[i] != null) {
  258. return true;
  259. } else {
  260. i++;
  261. }
  262. }
  263. return false;
  264. }
  265. public int next() {
  266. return _key[i++];
  267. }
  268. }
  269. /**
  270. * Iterator over keys
  271. */
  272. private class IntHashMapValueIterator implements Iterator, Serializable {
  273. private int i = 0;
  274. public IntHashMapValueIterator() {
  275. i = 0;
  276. }
  277. public boolean hasNext() {
  278. while (i < _key.length) {
  279. if (_value[i] != null) {
  280. return true;
  281. } else {
  282. i++;
  283. }
  284. }
  285. return false;
  286. }
  287. public Object next() {
  288. return _value[i++];
  289. }
  290. /**
  291. * Removes from the underlying collection the last element returned by the
  292. * iterator (optional operation).
  293. * @throws UnsupportedOperationException if the <tt>remove</tt>
  294. * operation is not supported by this Iterator.
  295. */
  296. public void remove() {
  297. throw new UnsupportedOperationException("remove");
  298. }
  299. }
  300. /**
  301. * Iterator over values
  302. */
  303. private class IntHashMapValueIteratorOLD implements Iterator, Serializable {
  304. private IntHashMapKeyIterator k;
  305. public IntHashMapValueIteratorOLD() {
  306. k = new IntHashMapKeyIterator();
  307. }
  308. public boolean hasNext() {
  309. return k.hasNext();
  310. }
  311. public Object next() {
  312. return get(k.next());
  313. }
  314. public void remove() {
  315. throw new UnsupportedOperationException("remove() is not supported on IntHashMapValueIterator");
  316. }
  317. }
  318. }
  319. //
  320. // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
  321. // you may not use this file except in compliance with the License. You may obtain a copy of the
  322. // License at http://www.mozilla.org/MPL/
  323. //
  324. // Software distributed under the License is distributed on an "AS IS" basis,
  325. // WITHOUT WARRANTY OF ANY KIND, either express or implied.
  326. // See the License for the specific language governing rights and limitations under the License.
  327. //
  328. // The Original Code is: all this file.
  329. //
  330. // The Initial Developer of the Original Code is Dave Hale and Dominique Devienne of Landmark Graphics;
  331. // the code was retrofitted to JDK 1.4 by Michael Kay, Saxonica.
  332. //
  333. // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
  334. //
  335. // Contributor(s): none.