Guest User

Untitled

a guest
Dec 13th, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.50 KB | None | 0 0
  1. package net.coderodde.util;
  2.  
  3. import java.util.NoSuchElementException;
  4. import java.util.Objects;
  5.  
  6. /**
  7. * This class implements a sorted map mapping integer keys to values of
  8. * arbitrary type.
  9. *
  10. * @author Rodion "rodde" Efremov
  11. * @version 1.6 (Dec 9, 2017)
  12. * @param <V> the type of values.
  13. */
  14. public final class VanEmdeBoasTreeIntMap<V> {
  15.  
  16. /**
  17. * The minimum universe size a node of a van Emde Boas tree can hold.
  18. */
  19. private static final int MINIMUM_UNIVERSE_SIZE = 2;
  20.  
  21. /**
  22. * The value used to denote the absence of an integer key.
  23. */
  24. private static final int NULL_KEY = -1;
  25.  
  26. /**
  27. * Used to denote that there is an integer mapped to a {@code null} value.
  28. */
  29. private final V NULL_VALUE = (V) new Object();
  30.  
  31. /**
  32. * This static inner class implements a node in a van Emde Boas tree.
  33. */
  34. private static final class VEBTree {
  35.  
  36. /**
  37. * The universe size of this vEB node.
  38. */
  39. private final int universeSize;
  40.  
  41. /**
  42. * The shift length for computing the high indices.
  43. */
  44. private final int highShift;
  45.  
  46. /**
  47. * The mask used to compute the low indices.
  48. */
  49. private final int lowMask;
  50.  
  51. /**
  52. * The minimum integer key in the tree starting from this node.
  53. */
  54. private int min;
  55.  
  56. /**
  57. * The maximum integer key in the tree starting from this node.
  58. */
  59. private int max;
  60.  
  61. /**
  62. * The summary vEB-tree.
  63. */
  64. private final VEBTree summary;
  65.  
  66. /**
  67. * The children nodes of this vEB node.
  68. */
  69. private final VEBTree[] cluster;
  70.  
  71. VEBTree(int universeSize) {
  72. this.universeSize = universeSize;
  73.  
  74. int universeSizeLowerSquare = lowerSquare(universeSize);
  75.  
  76. this.lowMask = universeSizeLowerSquare - 1;
  77. this.highShift =
  78. Integer.numberOfTrailingZeros(universeSizeLowerSquare);
  79.  
  80. this.min = NULL_KEY;
  81. this.max = NULL_KEY;
  82.  
  83. if (universeSize != MINIMUM_UNIVERSE_SIZE) {
  84. int upperUniverseSizeSquare = upperSquare(universeSize);
  85. int lowerUniverseSizeSquare = lowerSquare(universeSize);
  86. this.summary = new VEBTree(upperUniverseSizeSquare);
  87. this.cluster = new VEBTree[upperUniverseSizeSquare];
  88.  
  89. for (int i = 0; i != upperUniverseSizeSquare; ++i) {
  90. this.cluster[i] = new VEBTree(lowerUniverseSizeSquare);
  91. }
  92. } else {
  93. this.summary = null;
  94. this.cluster = null;
  95. }
  96. }
  97.  
  98. int getUniverseSize() {
  99. return universeSize;
  100. }
  101.  
  102. int getMinimumKey() {
  103. return min;
  104. }
  105.  
  106. int getMaximumKey() {
  107. return max;
  108. }
  109.  
  110. int getSuccessor(int x) {
  111. if (universeSize == MINIMUM_UNIVERSE_SIZE) {
  112. if (x == 0 && max == 1) {
  113. return 1;
  114. }
  115.  
  116. return NULL_KEY;
  117. }
  118.  
  119. if (min != NULL_KEY && x < min) {
  120. return min;
  121. }
  122.  
  123. int maximumLow = cluster[high(x)].getMaximumKey();
  124.  
  125. if (maximumLow != NULL_KEY && low(x) < maximumLow) {
  126. int offset = cluster[high(x)].getSuccessor(low(x));
  127. return index(high(x), offset);
  128. }
  129.  
  130. int successorCluster = summary.getSuccessor(high(x));
  131.  
  132. if (successorCluster == NULL_KEY) {
  133. return NULL_KEY;
  134. }
  135.  
  136. int offset = cluster[successorCluster].getMinimumKey();
  137. return index(successorCluster, offset);
  138. }
  139.  
  140. int getPredecessor(int x) {
  141. if (universeSize == MINIMUM_UNIVERSE_SIZE) {
  142. if (min == NULL_KEY) {
  143. return NULL_KEY;
  144. }
  145.  
  146. if (x == 1 && min == 0) {
  147. return 0;
  148. }
  149.  
  150. return NULL_KEY;
  151. }
  152.  
  153. if (max != NULL_KEY && x > max) {
  154. return max;
  155. }
  156.  
  157. int minimumLow = cluster[high(x)].getMinimumKey();
  158.  
  159. if (minimumLow != NULL_KEY && low(x) > minimumLow) {
  160. int offset = cluster[high(x)].getPredecessor(low(x));
  161. return index(high(x), offset);
  162. }
  163.  
  164. int predecessorCluster = summary.getPredecessor(high(x));
  165.  
  166. if (predecessorCluster == NULL_KEY) {
  167. if (min != NULL_KEY && x > min) {
  168. return min;
  169. }
  170.  
  171. return NULL_KEY;
  172. }
  173.  
  174. int offset = cluster[predecessorCluster].getMaximumKey();
  175. return index(predecessorCluster, offset);
  176. }
  177.  
  178. void treeInsert(int x) {
  179. if (min == NULL_KEY) {
  180. emptyTreeInsert(x);
  181. return;
  182. }
  183.  
  184. if (x < min) {
  185. int tmp = x;
  186. x = min;
  187. min = tmp;
  188. }
  189.  
  190. if (universeSize != MINIMUM_UNIVERSE_SIZE) {
  191. int minimum = cluster[high(x)].getMinimumKey();
  192.  
  193. if (minimum == NULL_KEY) {
  194. summary.treeInsert(high(x));
  195. cluster[high(x)].emptyTreeInsert(low(x));
  196. } else {
  197. cluster[high(x)].treeInsert(low(x));
  198. }
  199. }
  200.  
  201. if (max < x) {
  202. max = x;
  203. }
  204. }
  205.  
  206. void treeDelete(int x) {
  207. if (min == max) {
  208. min = NULL_KEY;
  209. max = NULL_KEY;
  210. return;
  211. }
  212.  
  213. if (universeSize == MINIMUM_UNIVERSE_SIZE) {
  214. if (x == 0) {
  215. min = 1;
  216. } else {
  217. max = 0;
  218. }
  219.  
  220. max = min;
  221. return;
  222. }
  223.  
  224. if (min == x) {
  225. int firstCluster = summary.getMinimumKey();
  226. x = index(firstCluster, cluster[firstCluster].getMinimumKey());
  227. min = x;
  228. }
  229.  
  230. cluster[high(x)].treeDelete(low(x));
  231.  
  232. if (cluster[high(x)].getMinimumKey() == NULL_KEY) {
  233. summary.treeDelete(high(x));
  234.  
  235. if (x == max) {
  236. int summaryMaximum = summary.getMaximumKey();
  237.  
  238. if (summaryMaximum == NULL_KEY) {
  239. max = min;
  240. } else {
  241. int maximumKey =
  242. cluster[summaryMaximum].getMaximumKey();
  243. max = index(summaryMaximum, maximumKey);
  244. }
  245. }
  246. } else if (x == max) {
  247. int maximumKey = cluster[high(x)].getMaximumKey();
  248. max = index(high(x), maximumKey);
  249. }
  250. }
  251.  
  252. private void emptyTreeInsert(int x) {
  253. min = x;
  254. max = x;
  255. }
  256.  
  257. private int high(int x) {
  258. return x >>> highShift;
  259. }
  260.  
  261. private int low(int x) {
  262. return x & lowMask;
  263. }
  264.  
  265. private int index(int x, int y) {
  266. return (x << highShift) | (y & lowMask);
  267. }
  268. }
  269.  
  270. private static int upperSquare(int number) {
  271. double exponent = Math.ceil(Math.log(number) / Math.log(2.0) / 2.0);
  272. return (int) Math.pow(2.0, exponent);
  273. }
  274.  
  275. private static int lowerSquare(int number) {
  276. double exponent = Math.floor(Math.log(number) / Math.log(2.0) / 2.0);
  277. return (int) Math.pow(2.0, exponent);
  278. }
  279.  
  280. private final VEBTree root;
  281. private final int minimumKey;
  282. private final int maximumKey;
  283. private final V[] table;
  284. private int size;
  285.  
  286. public VanEmdeBoasTreeIntMap(int minimumKey, int maximumKey) {
  287. checkBounds(minimumKey, maximumKey);
  288. this.minimumKey = minimumKey;
  289. this.maximumKey = maximumKey;
  290. int universeSize = maximumKey - minimumKey + 1;
  291. universeSize = fixUniverseSize(universeSize);
  292. this.root = new VEBTree(universeSize);
  293. this.table = (V[]) new Object[universeSize];
  294. }
  295.  
  296. public int size() {
  297. return size;
  298. }
  299.  
  300. public boolean isEmpty() {
  301. return size == 0;
  302. }
  303.  
  304. public int getMinimumKey() {
  305. return size != 0 ? root.min + minimumKey : this.maximumKey + 1;
  306. }
  307.  
  308. public int getMaximumKey() {
  309. return size != 0 ? root.max + minimumKey : this.minimumKey - 1;
  310. }
  311.  
  312. public int getNextIntKey(int key) {
  313. checkKey(key);
  314. int nextKey = root.getSuccessor(key - minimumKey);
  315. return nextKey == NULL_KEY ?
  316. this.minimumKey - 1 :
  317. nextKey + minimumKey;
  318. }
  319.  
  320. public int getPreviousIntKey(int key) {
  321. checkKey(key);
  322. int previousKey = root.getPredecessor(key - minimumKey);
  323. return previousKey == NULL_KEY ?
  324. this.maximumKey + 1 :
  325. previousKey + minimumKey;
  326. }
  327.  
  328. public boolean containsKey(int key) {
  329. checkKey(key);
  330. return table[key - minimumKey] != null;
  331. }
  332.  
  333. public V get(int key) {
  334. checkKey(key);
  335. V value = table[key - minimumKey];
  336. return (value == null || value == NULL_VALUE) ? null : value;
  337. }
  338.  
  339. public V put(int key, V value) {
  340. checkKey(key);
  341. // Translate the key:
  342. key -= minimumKey;
  343. V currentValue = table[key];
  344.  
  345. if (currentValue != null) {
  346. // key is present in this map.
  347. V oldValue = table[key];
  348. table[key] = value == null ? NULL_VALUE : value;
  349. return oldValue;
  350. } else {
  351. root.treeInsert(key);
  352. table[key] = value != null ? value : NULL_VALUE;
  353. size++;
  354. return null;
  355. }
  356. }
  357.  
  358. public V remove(int key) {
  359. checkKey(key);
  360. // Translate the key:
  361. key -= minimumKey;
  362. V value = table[key];
  363.  
  364. if (value != null) {
  365. // key is in this map.
  366. table[key] = null;
  367. root.treeDelete(key);
  368. size--;
  369. return value == NULL_VALUE ? null : value;
  370. } else {
  371. return null;
  372. }
  373. }
  374.  
  375. public void clear() {
  376. int key = root.min;
  377. int nextKey;
  378.  
  379. for (int i = 0; i != size; ++i) {
  380. nextKey = root.getSuccessor(key);
  381. root.treeDelete(key); // Remove key.
  382. table[key] = null; // Remove value.
  383. key = nextKey;
  384. }
  385.  
  386. size = 0;
  387. }
  388.  
  389. /**
  390. * This inner interface specifies the API for key iterators.
  391. */
  392. public interface KeyIterator {
  393.  
  394. /**
  395. * Returns {@code true} only if there is more keys to iterate.
  396. *
  397. * @return {@code true} if there is more keys to iterate.
  398. */
  399. public boolean hasNextKey();
  400.  
  401. /**
  402. * Returns the next key in the sorted iteration order.
  403. *
  404. * @return the next key.
  405. */
  406. public int nextKey();
  407.  
  408. /**
  409. * Removes the entire key/value pair of the current key.
  410. */
  411. public void removeKey();
  412. }
  413.  
  414. /**
  415. * Holds a mapping while iterating the data structure.
  416. *
  417. * @param <V> the value type.
  418. */
  419. public static final class KeyValueMapping<V> {
  420.  
  421. public int key;
  422. public V value;
  423.  
  424. @Override
  425. public boolean equals(Object o) {
  426. if (o == this) {
  427. return true;
  428. }
  429.  
  430. if (o == null) {
  431. return false;
  432. }
  433.  
  434. if (!getClass().equals(o.getClass())) {
  435. return false;
  436. }
  437.  
  438. KeyValueMapping<V> other = (KeyValueMapping<V>) o;
  439. return key == other.key && Objects.equals(value, other.value);
  440. }
  441. }
  442.  
  443. /**
  444. * This inner interface specifies the API for the key/value iterators.
  445. *
  446. * @param <V> the value type.
  447. */
  448. public interface KeyValueIterator<V> {
  449.  
  450. /**
  451. * Returns {@code true} only if there is more key/value pairs to
  452. * iterate.
  453. *
  454. * @return {@code true} if there is more pairs to iterate.
  455. */
  456. public boolean hasNextKeyValuePair();
  457.  
  458. /**
  459. * Loads the current key/value pair.
  460. *
  461. * @param keyValueMapping the key/value pair where to store the data.
  462. */
  463. public void nextKeyValuePair(KeyValueMapping<V> keyValueMapping);
  464.  
  465. /**
  466. * Removes the previously iterated key/value pair.
  467. */
  468. public void removeKeyValuePair();
  469. }
  470.  
  471. /**
  472. * Implements the key iterator that traverses the integers in order via the
  473. * underlying van Emde Boas tree.
  474. */
  475. public final class TreeKeyIterator implements KeyIterator {
  476.  
  477. private int iterated;
  478. private int lastReturned;
  479.  
  480. /**
  481. * {@inheritDoc }
  482. */
  483. @Override
  484. public boolean hasNextKey() {
  485. return iterated < size;
  486. }
  487.  
  488. /**
  489. * {@inheritDoc }
  490. */
  491. @Override
  492. public int nextKey() {
  493. if (!hasNextKey()) {
  494. throw new NoSuchElementException("Nothing to iterate left.");
  495. }
  496.  
  497. if (iterated == 0) {
  498. lastReturned = getMinimumKey();
  499. iterated++;
  500. return lastReturned;
  501. } else {
  502. int next = getNextIntKey(lastReturned);
  503. lastReturned = next;
  504. iterated++;
  505. return next;
  506. }
  507. }
  508.  
  509. /**
  510. * {@inheritDoc }
  511. */
  512. @Override
  513. public void removeKey() {
  514. if (iterated == 0) {
  515. throw new IllegalStateException(
  516. "No current key to remove yet.");
  517. }
  518.  
  519. remove(lastReturned);
  520. }
  521. }
  522.  
  523. /**
  524. * Implements a key iterator that traverses directly the mapping table. This
  525. * may provide a speed up over the {@link TreeKeyIterator} if the table is
  526. * densely populated.
  527. */
  528. public final class TableKeyIterator implements KeyIterator {
  529.  
  530. private int iterated;
  531. private int currentIndex;
  532.  
  533. /**
  534. * {@inheritDoc }
  535. */
  536. @Override
  537. public boolean hasNextKey() {
  538. return iterated < size;
  539. }
  540.  
  541. /**
  542. * {@inheritDoc }
  543. */
  544. @Override
  545. public int nextKey() {
  546. if (!hasNextKey()) {
  547. throw new NoSuchElementException("Nothing to iterate left.");
  548. }
  549.  
  550. if (iterated == 0) {
  551. currentIndex = getMinimumKey() - minimumKey;
  552. iterated++;
  553. return getMinimumKey();
  554. } else {
  555. for (currentIndex++;
  556. table[currentIndex] == null;
  557. currentIndex++) {}
  558.  
  559. iterated++;
  560. return currentIndex + minimumKey;
  561. }
  562. }
  563.  
  564. /**
  565. * {@inheritDoc }
  566. */
  567. @Override
  568. public void removeKey() {
  569. if (iterated == 0) {
  570. throw new IllegalStateException(
  571. "No current key to remove yet.");
  572. }
  573.  
  574. remove(currentIndex + minimumKey);
  575. }
  576. }
  577.  
  578. /**
  579. * Implements the key iterator that traverses the integers in order via the
  580. * underlying van Emde Boas tree.
  581. */
  582. public final class TreeKeyValueIterator implements KeyValueIterator<V> {
  583.  
  584. private int iterated;
  585. private int lastReturned;
  586.  
  587. /**
  588. * {@inheritDoc }
  589. */
  590. @Override
  591. public boolean hasNextKeyValuePair() {
  592. return iterated < size;
  593. }
  594.  
  595. /**
  596. * {@inheritDoc }
  597. */
  598. @Override
  599. public void nextKeyValuePair(KeyValueMapping<V> keyValueMapping) {
  600. if (!hasNextKeyValuePair()) {
  601. throw new NoSuchElementException("Nothing to iterate left.");
  602. }
  603.  
  604. if (iterated == 0) {
  605. lastReturned = getMinimumKey();
  606. iterated++;
  607. V value = table[lastReturned - minimumKey];
  608. keyValueMapping.key = lastReturned;
  609. keyValueMapping.value = value == NULL_VALUE ? null : value;
  610. } else {
  611. lastReturned = getNextIntKey(lastReturned);
  612. iterated++;
  613. V value = table[lastReturned - minimumKey];
  614. keyValueMapping.key = lastReturned;
  615. keyValueMapping.value = value == NULL_VALUE ? null : value;
  616. }
  617. }
  618.  
  619. /**
  620. * {@inheritDoc }
  621. */
  622. @Override
  623. public void removeKeyValuePair() {
  624. if (iterated == 0) {
  625. throw new IllegalStateException(
  626. "No current key to remove yet.");
  627. }
  628.  
  629. remove(lastReturned);
  630. }
  631. }
  632.  
  633. /**
  634. * Implements a key iterator that traverses directly the mapping table. This
  635. * may provide a speed up over the {@link TreeKeyIterator} if the table is
  636. * densely populated.
  637. */
  638. public final class TableKeyValueIterator implements KeyValueIterator<V> {
  639.  
  640. private int iterated;
  641. private int currentIndex;
  642.  
  643. /**
  644. * {@inheritDoc }
  645. */
  646. @Override
  647. public boolean hasNextKeyValuePair() {
  648. return iterated < size;
  649. }
  650.  
  651. /**
  652. * {@inheritDoc }
  653. */
  654. @Override
  655. public void nextKeyValuePair(KeyValueMapping<V> keyValueMapping) {
  656. if (!hasNextKeyValuePair()) {
  657. throw new NoSuchElementException("Nothing to iterate left.");
  658. }
  659.  
  660. if (iterated == 0) {
  661. currentIndex = getMinimumKey() - minimumKey;
  662. V value = table[currentIndex];
  663. iterated++;
  664. keyValueMapping.key = getMinimumKey();
  665. keyValueMapping.value = value == NULL_VALUE ?
  666. null :
  667. value;
  668. } else {
  669. for (currentIndex++;
  670. table[currentIndex] == null;
  671. currentIndex++) {}
  672.  
  673. iterated++;
  674. V value = table[currentIndex];
  675. keyValueMapping.key = currentIndex + minimumKey;
  676. keyValueMapping.value = value == NULL_VALUE ?
  677. null :
  678. value;
  679. }
  680. }
  681.  
  682. /**
  683. * {@inheritDoc }
  684. */
  685. @Override
  686. public void removeKeyValuePair() {
  687. if (iterated == 0) {
  688. throw new IllegalStateException(
  689. "No current key to remove yet.");
  690. }
  691.  
  692. remove(currentIndex + minimumKey);
  693. }
  694. }
  695.  
  696. public float getTableDensityFactor() {
  697. if (size == 0) {
  698. return 0.0f;
  699. }
  700.  
  701. int rangeLength = getMaximumKey() - getMinimumKey() + 1;
  702. return (1.0f * size) / rangeLength;
  703. }
  704.  
  705. public KeyIterator treeKeyIterator() {
  706. return new TreeKeyIterator();
  707. }
  708.  
  709. public KeyIterator tableKeyIterator() {
  710. return new TableKeyIterator();
  711. }
  712.  
  713. public KeyValueIterator<V> treeKeyValueIterator() {
  714. return new TreeKeyValueIterator();
  715. }
  716.  
  717. public KeyValueIterator<V> tableKeyValueIterator() {
  718. return new TableKeyValueIterator();
  719. }
  720.  
  721. public static final class Mapping<V> {
  722. public int key;
  723. public V value;
  724.  
  725. @Override
  726. public String toString() {
  727. return "(" + key + " -> " + value + ")";
  728. }
  729. }
  730.  
  731. public static final class MappingIterator<V> {
  732.  
  733. private final VanEmdeBoasTreeIntMap<V> tree;
  734. private int iterated = 0;
  735. private int lastReturned;
  736.  
  737. MappingIterator(VanEmdeBoasTreeIntMap<V> tree) {
  738. this.tree = tree;
  739. }
  740.  
  741. public boolean hasNext() {
  742. return iterated < tree.size;
  743. }
  744.  
  745. public void next(Mapping<V> mapping) {
  746. if (!hasNext()) {
  747. throw new NoSuchElementException("Nothing to iterate left.");
  748. }
  749.  
  750. if (iterated == 0) {
  751. lastReturned = tree.getMinimumKey();
  752. iterated++;
  753. mapping.key = lastReturned;
  754. mapping.value = tree.table[lastReturned - tree.minimumKey];
  755. } else {
  756. int next = tree.getNextIntKey(lastReturned);
  757. lastReturned = next;
  758. iterated++;
  759. mapping.key = lastReturned;
  760. mapping.value = tree.table[lastReturned - tree.minimumKey];
  761. }
  762. }
  763. }
  764.  
  765. public MappingIterator<V> mappingIterator() {
  766. return new MappingIterator<>(this);
  767. }
  768.  
  769. private void checkBounds(int minimumKey, int maximumKey) {
  770. if (minimumKey > maximumKey) {
  771. throw new IllegalArgumentException(
  772. "minimumKey(" + minimumKey + ") > " +
  773. "maximumKey(" + maximumKey + ")");
  774. }
  775. }
  776.  
  777. private int fixUniverseSize(int requestedUniverseSize) {
  778. int tmp = Integer.highestOneBit(requestedUniverseSize);
  779. return tmp == requestedUniverseSize ?
  780. requestedUniverseSize :
  781. (tmp << 1);
  782. }
  783.  
  784. private void checkKey(int key) {
  785. if (key < minimumKey) {
  786. throw new IllegalArgumentException(
  787. "The given key (" + key + ") is too small. Must be at " +
  788. "least " + minimumKey + ".");
  789. }
  790.  
  791. if (key > maximumKey) {
  792. throw new IllegalArgumentException(
  793. "The given key (" + key + ") is too large. Must be at " +
  794. "most " + maximumKey + ".");
  795. }
  796. }
  797. }
  798.  
  799. package net.coderodde.util;
  800.  
  801. import net.coderodde.util.VanEmdeBoasTreeIntMap.KeyValueMapping;
  802. import static org.junit.Assert.assertEquals;
  803. import static org.junit.Assert.assertFalse;
  804. import static org.junit.Assert.assertNull;
  805. import static org.junit.Assert.assertTrue;
  806. import org.junit.Test;
  807.  
  808. public class VanEmdeBoasTreeIntMapTest {
  809.  
  810. @Test
  811. public void testSize() {
  812. VanEmdeBoasTreeIntMap<Integer> tree =
  813. new VanEmdeBoasTreeIntMap<>(-10, 10);
  814.  
  815. for (int i = -10, size = 0; i <= 10; ++i, ++size) {
  816. assertEquals(size, tree.size());
  817. tree.put(i, i);
  818. assertEquals(size + 1, tree.size());
  819. }
  820. }
  821.  
  822. @Test
  823. public void testIsEmpty() {
  824. VanEmdeBoasTreeIntMap<Integer> tree =
  825. new VanEmdeBoasTreeIntMap<>(-10, 10);
  826.  
  827. assertTrue(tree.isEmpty());
  828. tree.put(0, 0);
  829. assertFalse(tree.isEmpty());
  830. tree.put(1, 1);
  831. assertFalse(tree.isEmpty());
  832. tree.remove(0);
  833. assertFalse(tree.isEmpty());
  834. tree.remove(1);
  835. assertTrue(tree.isEmpty());
  836. }
  837.  
  838. @Test
  839. public void testGetMinimumKey() {
  840. VanEmdeBoasTreeIntMap<Integer> tree =
  841. new VanEmdeBoasTreeIntMap<>(-5, 4);
  842.  
  843. assertEquals(5, tree.getMinimumKey());
  844.  
  845. for (int i = 4; i >= -5; --i) {
  846. tree.put(i, i);
  847. assertEquals(i, tree.getMinimumKey());
  848. }
  849.  
  850. tree.clear();
  851.  
  852. assertEquals(5, tree.getMinimumKey());
  853.  
  854. tree = new VanEmdeBoasTreeIntMap<>(Integer.MAX_VALUE - 5,
  855. Integer.MAX_VALUE);
  856.  
  857. assertEquals(Integer.MIN_VALUE, tree.getMinimumKey());
  858. }
  859.  
  860. @Test
  861. public void testGetMaximumKey() {
  862. VanEmdeBoasTreeIntMap<Integer> tree =
  863. new VanEmdeBoasTreeIntMap<>(-5, 4);
  864.  
  865. assertEquals(-6, tree.getMaximumKey());
  866.  
  867. for (int i = -5; i <= 4; ++i) {
  868. tree.put(i, i);
  869. assertEquals(i, tree.getMaximumKey());
  870. }
  871.  
  872. tree.clear();
  873.  
  874. assertEquals(-6, tree.getMaximumKey());
  875.  
  876. tree = new VanEmdeBoasTreeIntMap<>(Integer.MIN_VALUE,
  877. Integer.MIN_VALUE + 5);
  878.  
  879. assertEquals(Integer.MAX_VALUE, tree.getMaximumKey());
  880. }
  881.  
  882. @Test
  883. public void testGetNextIntKey() {
  884. VanEmdeBoasTreeIntMap<Integer> tree =
  885. new VanEmdeBoasTreeIntMap<>(-3, 3);
  886.  
  887. tree.put(-3, -3);
  888. tree.put(-1, -1);
  889. tree.put(0, 0);
  890. tree.put(2, 2);
  891.  
  892. assertEquals(-1, tree.getNextIntKey(-3));
  893. assertEquals(-1, tree.getNextIntKey(-2));
  894.  
  895. assertEquals(0, tree.getNextIntKey(-1));
  896. assertEquals(2, tree.getNextIntKey(0));
  897. assertEquals(2, tree.getNextIntKey(1));
  898. assertEquals(-4, tree.getNextIntKey(2));
  899. assertEquals(-4, tree.getNextIntKey(3));
  900.  
  901. tree.clear();
  902.  
  903. for (int i = -3; i <= 3; ++i) {
  904. assertEquals(-4, tree.getNextIntKey(i));
  905. }
  906. }
  907.  
  908. @Test
  909. public void testGetPreviousIntKey() {
  910. VanEmdeBoasTreeIntMap<Integer> tree =
  911. new VanEmdeBoasTreeIntMap<>(-3, 3);
  912.  
  913. tree.put(-3, -3);
  914. tree.put(-1, -1);
  915. tree.put(0, 0);
  916. tree.put(2, 2);
  917.  
  918. assertEquals(2, tree.getPreviousIntKey(3));
  919.  
  920. assertEquals(0, tree.getPreviousIntKey(2));
  921. assertEquals(0, tree.getPreviousIntKey(1));
  922.  
  923. assertEquals(-1, tree.getPreviousIntKey(0));
  924. assertEquals(-3, tree.getPreviousIntKey(-1));
  925. assertEquals(-3, tree.getPreviousIntKey(-2));
  926. assertEquals(4, tree.getPreviousIntKey(-3));
  927.  
  928. tree.clear();
  929.  
  930. for (int i = -3; i <= 3; ++i) {
  931. assertEquals(4, tree.getPreviousIntKey(i));
  932. }
  933. }
  934.  
  935. @Test
  936. public void testContains() {
  937. VanEmdeBoasTreeIntMap<Integer> tree =
  938. new VanEmdeBoasTreeIntMap<>(-5, -1);
  939.  
  940. tree.put(-5, null);
  941. tree.put(-3, -3);
  942. tree.put(-1, -1);
  943.  
  944. assertTrue(tree.containsKey(-5));
  945. assertTrue(tree.containsKey(-3));
  946. assertTrue(tree.containsKey(-1));
  947.  
  948. assertFalse(tree.containsKey(-4));
  949. assertFalse(tree.containsKey(-2));
  950. }
  951.  
  952. @Test
  953. public void testGet() {
  954. VanEmdeBoasTreeIntMap<Integer> tree =
  955. new VanEmdeBoasTreeIntMap<>(-5, -1);
  956.  
  957. tree.put(-5, null);
  958. tree.put(-3, -13);
  959. tree.put(-1, -11);
  960.  
  961. assertNull(tree.get(-5));
  962. assertEquals(Integer.valueOf(-11), tree.get(-1));
  963. assertEquals(Integer.valueOf(-13), tree.get(-3));
  964. }
  965.  
  966. @Test
  967. public void testPut() {
  968. VanEmdeBoasTreeIntMap<Integer> tree =
  969. new VanEmdeBoasTreeIntMap<>(-5, 10);
  970.  
  971. for (int i = -2; i <= 4; ++i) {
  972. assertFalse(tree.containsKey(i));
  973. assertNull(tree.put(i, 2 * i));
  974. assertTrue(tree.containsKey(i));
  975. }
  976.  
  977. for (int i = -3; i >= -5; --i) {
  978. assertFalse(tree.containsKey(i));
  979. assertNull(tree.get(i));
  980. }
  981.  
  982. assertTrue(tree.containsKey(0));
  983. tree.remove(0);
  984. assertFalse(tree.containsKey(0));
  985. }
  986.  
  987. @Test(expected = IllegalArgumentException.class)
  988. public void testLowerBound() {
  989. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  990.  
  991. tree.put(-5, "-5");
  992. }
  993.  
  994. @Test(expected = IllegalArgumentException.class)
  995. public void testUpperBound() {
  996. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  997.  
  998. tree.put(5, "5");
  999. }
  1000.  
  1001. @Test
  1002. public void testTreeKeyIterator() {
  1003. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  1004.  
  1005. for (int i = 4; i >= -4; --i) {
  1006. tree.put(i, null);
  1007. }
  1008.  
  1009. VanEmdeBoasTreeIntMap.KeyIterator iterator = tree.treeKeyIterator();
  1010.  
  1011. for (int i = -4; i <= 4; ++i) {
  1012. assertTrue(iterator.hasNextKey());
  1013. assertEquals(i, iterator.nextKey());
  1014. }
  1015.  
  1016. assertEquals(9, tree.size());
  1017.  
  1018. iterator = tree.treeKeyIterator();
  1019.  
  1020. assertEquals(-4, iterator.nextKey());
  1021. iterator.removeKey();
  1022. assertEquals(-3, iterator.nextKey());
  1023. assertEquals(-2, iterator.nextKey());
  1024. assertEquals(-1, iterator.nextKey());
  1025. iterator.removeKey();
  1026.  
  1027. assertFalse(tree.containsKey(-4));
  1028. assertTrue(tree.containsKey(-3));
  1029. assertTrue(tree.containsKey(-2));
  1030. assertFalse(tree.containsKey(-1));
  1031.  
  1032. assertEquals(7, tree.size());
  1033. }
  1034.  
  1035. @Test
  1036. public void testTableKeyIterator() {
  1037. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  1038.  
  1039. for (int i = 4; i >= -4; --i) {
  1040. tree.put(i, null);
  1041. }
  1042.  
  1043. VanEmdeBoasTreeIntMap.KeyIterator iterator = tree.tableKeyIterator();
  1044.  
  1045. for (int i = -4; i <= 4; ++i) {
  1046. assertTrue(iterator.hasNextKey());
  1047. assertEquals(i, iterator.nextKey());
  1048. }
  1049.  
  1050. assertEquals(9, tree.size());
  1051.  
  1052. iterator = tree.treeKeyIterator();
  1053.  
  1054. assertEquals(-4, iterator.nextKey());
  1055. iterator.removeKey();
  1056. assertEquals(-3, iterator.nextKey());
  1057. assertEquals(-2, iterator.nextKey());
  1058. assertEquals(-1, iterator.nextKey());
  1059. iterator.removeKey();
  1060.  
  1061. assertFalse(tree.containsKey(-4));
  1062. assertTrue(tree.containsKey(-3));
  1063. assertTrue(tree.containsKey(-2));
  1064. assertFalse(tree.containsKey(-1));
  1065.  
  1066. assertEquals(7, tree.size());
  1067. }
  1068.  
  1069. @Test
  1070. public void testTreeKeyValueIterator() {
  1071. KeyValueMapping<String> mapping = new KeyValueMapping<>();
  1072. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  1073.  
  1074. for (int i = 4; i >= -4; --i) {
  1075. tree.put(i, "" + i);
  1076. }
  1077.  
  1078. VanEmdeBoasTreeIntMap.KeyValueIterator<String> iterator =
  1079. tree.treeKeyValueIterator();
  1080.  
  1081. for (int i = -4; i <= 4; ++i) {
  1082. assertTrue(iterator.hasNextKeyValuePair());
  1083. iterator.nextKeyValuePair(mapping);
  1084. assertEquals(i, mapping.key);
  1085. assertEquals("" + i, mapping.value);
  1086. }
  1087.  
  1088. assertEquals(9, tree.size());
  1089.  
  1090. iterator = tree.treeKeyValueIterator();
  1091. iterator.nextKeyValuePair(mapping);
  1092.  
  1093. assertEquals(-4, mapping.key);
  1094. assertEquals("-4", mapping.value);
  1095.  
  1096. iterator.removeKeyValuePair();
  1097. iterator.nextKeyValuePair(mapping);
  1098. assertEquals(-3, mapping.key);
  1099. assertEquals("-3", mapping.value);
  1100.  
  1101. iterator.nextKeyValuePair(mapping);
  1102. assertEquals(-2, mapping.key);
  1103. assertEquals("-2", mapping.value);
  1104.  
  1105. iterator.nextKeyValuePair(mapping);
  1106. assertEquals(-1, mapping.key);
  1107. assertEquals("-1", mapping.value);
  1108. iterator.removeKeyValuePair();
  1109.  
  1110. assertFalse(tree.containsKey(-4));
  1111. assertTrue(tree.containsKey(-3));
  1112. assertTrue(tree.containsKey(-2));
  1113. assertFalse(tree.containsKey(-1));
  1114.  
  1115. assertEquals(7, tree.size());
  1116. }
  1117.  
  1118. @Test
  1119. public void testTableKeyValueIterator() {
  1120. KeyValueMapping<String> mapping = new KeyValueMapping<>();
  1121. VanEmdeBoasTreeIntMap<String> tree = new VanEmdeBoasTreeIntMap<>(-4, 4);
  1122.  
  1123. for (int i = 4; i >= -4; --i) {
  1124. tree.put(i, "" + i);
  1125. }
  1126.  
  1127. VanEmdeBoasTreeIntMap.KeyValueIterator<String> iterator =
  1128. tree.tableKeyValueIterator();
  1129.  
  1130. for (int i = -4; i <= 4; ++i) {
  1131. assertTrue(iterator.hasNextKeyValuePair());
  1132. iterator.nextKeyValuePair(mapping);
  1133. assertEquals(i, mapping.key);
  1134. assertEquals("" + i, mapping.value);
  1135. }
  1136.  
  1137. assertEquals(9, tree.size());
  1138.  
  1139. iterator = tree.treeKeyValueIterator();
  1140. iterator.nextKeyValuePair(mapping);
  1141.  
  1142. assertEquals(-4, mapping.key);
  1143. assertEquals("-4", mapping.value);
  1144.  
  1145. iterator.removeKeyValuePair();
  1146. iterator.nextKeyValuePair(mapping);
  1147. assertEquals(-3, mapping.key);
  1148. assertEquals("-3", mapping.value);
  1149.  
  1150. iterator.nextKeyValuePair(mapping);
  1151. assertEquals(-2, mapping.key);
  1152. assertEquals("-2", mapping.value);
  1153.  
  1154. iterator.nextKeyValuePair(mapping);
  1155. assertEquals(-1, mapping.key);
  1156. assertEquals("-1", mapping.value);
  1157. iterator.removeKeyValuePair();
  1158.  
  1159. assertFalse(tree.containsKey(-4));
  1160. assertTrue(tree.containsKey(-3));
  1161. assertTrue(tree.containsKey(-2));
  1162. assertFalse(tree.containsKey(-1));
  1163.  
  1164. assertEquals(7, tree.size());
  1165. }
  1166.  
  1167. @Test
  1168. public void testRemove() {
  1169. VanEmdeBoasTreeIntMap<Integer> tree = new VanEmdeBoasTreeIntMap<>(1, 5);
  1170.  
  1171. tree.put(3, 3);
  1172. tree.put(1, 1);
  1173. tree.put(5, 5);
  1174.  
  1175. assertTrue(tree.containsKey(1));
  1176. assertTrue(tree.containsKey(3));
  1177. assertTrue(tree.containsKey(5));
  1178.  
  1179. tree.put(1, null);
  1180.  
  1181. assertTrue(tree.containsKey(1));
  1182.  
  1183. tree.remove(1);
  1184.  
  1185. assertFalse(tree.containsKey(1));
  1186. }
  1187.  
  1188. @Test
  1189. public void clear() {
  1190. VanEmdeBoasTreeIntMap<Integer> tree =
  1191. new VanEmdeBoasTreeIntMap<>(3, 10);
  1192.  
  1193. for (int i = 4, sz = 0; i <= 8; ++i, ++sz) {
  1194. assertEquals(sz, tree.size());
  1195. tree.put(i, null);
  1196. assertEquals(sz + 1, tree.size());
  1197. }
  1198.  
  1199. assertEquals(5, tree.size());
  1200. tree.clear();
  1201. assertEquals(0, tree.size());
  1202.  
  1203. for (int i = 3; i <= 10; ++i) {
  1204. assertFalse(tree.containsKey(i));
  1205. assertNull(tree.get(i));
  1206. assertNull(tree.remove(i));
  1207. }
  1208. }
  1209. }
  1210.  
  1211. package net.coderodde.util;
  1212.  
  1213. import java.util.HashMap;
  1214. import java.util.Map;
  1215. import java.util.Random;
  1216. import java.util.TreeMap;
  1217. import net.coderodde.util.VanEmdeBoasTreeIntMap.KeyIterator;
  1218. import net.coderodde.util.VanEmdeBoasTreeIntMap.KeyValueIterator;
  1219. import net.coderodde.util.VanEmdeBoasTreeIntMap.KeyValueMapping;
  1220.  
  1221. /**
  1222. * This class benchmarks the {@link VanEmdeBoasTreeIntMap} against a
  1223. * {@link TreeMap} and {@link HashMap}.
  1224. *
  1225. * @author Rodion "rodde" Efremov
  1226. * @version 1.6 (Dec 13, 2017)
  1227. */
  1228. public final class Benchmark {
  1229.  
  1230. private static final int MINIMUM_KEY = -1000_000;
  1231. private static final int MAXIMUM_KEY = 1_000_000;
  1232. private static final int INTEGER_ARRAY_LENGTH = 1_500_000;
  1233. private static final Random RANDOM;
  1234.  
  1235. static {
  1236. long seed = System.currentTimeMillis();
  1237. System.out.println("Seed = " + seed);
  1238. RANDOM = new Random(seed);
  1239. }
  1240.  
  1241. public static void main(String[] args) {
  1242. warmup();
  1243.  
  1244. System.out.println();
  1245.  
  1246. benchmark();
  1247. }
  1248.  
  1249. private static void benchmark() {
  1250. Integer[] testArray = createRandomIntegerArray(INTEGER_ARRAY_LENGTH,
  1251. MINIMUM_KEY,
  1252. MAXIMUM_KEY);
  1253. benchmarkTreeMap(testArray);
  1254. System.out.println();
  1255. benchmarkHashMap(testArray);
  1256. System.out.println();
  1257. benchmarkVebMap(testArray);
  1258. }
  1259.  
  1260. private static void benchmarkTreeMap(Integer[] testArray) {
  1261. benchmarkMap(new TreeMap<>(), testArray);
  1262. }
  1263.  
  1264. private static void benchmarkHashMap(Integer[] testArray) {
  1265. benchmarkMap(new HashMap<>(), testArray);
  1266. }
  1267.  
  1268. private static void benchmarkVebMap(Integer[] testArray) {
  1269. System.out.println(
  1270.  
  1271. "--- " + VanEmdeBoasTreeIntMap.class.getSimpleName() + " ---");
  1272.  
  1273. long startTime;
  1274. long endTime;
  1275. long totalTime = 0L;
  1276.  
  1277. startTime = System.currentTimeMillis();
  1278. // Create.
  1279. VanEmdeBoasTreeIntMap<Integer> map =
  1280. new VanEmdeBoasTreeIntMap<>(MINIMUM_KEY, MAXIMUM_KEY);
  1281.  
  1282. endTime = System.currentTimeMillis();
  1283. totalTime += endTime - startTime;
  1284.  
  1285. System.out.println("Constructed a van Emde Boas tree in " +
  1286. (endTime - startTime) + " milliseconds.");
  1287.  
  1288. // put().
  1289. startTime = System.currentTimeMillis();
  1290.  
  1291. for (Integer i : testArray) {
  1292. map.put(i, i);
  1293. }
  1294.  
  1295. endTime = System.currentTimeMillis();
  1296. totalTime += endTime - startTime;
  1297.  
  1298. System.out.println(
  1299. "put() in " + (endTime - startTime) + " milliseconds.");
  1300.  
  1301. // Key iteration.
  1302. startTime = System.currentTimeMillis();
  1303. KeyIterator keyIterator = map.tableKeyIterator();
  1304.  
  1305. while (keyIterator.hasNextKey()) {
  1306. keyIterator.nextKey();
  1307. }
  1308.  
  1309. endTime = System.currentTimeMillis();
  1310. totalTime += endTime - startTime;
  1311.  
  1312. System.out.println(
  1313. "Key iteration in " + (endTime - startTime) + " milliseconds.");
  1314.  
  1315. // Entry set iteration.
  1316. startTime = System.currentTimeMillis();
  1317. KeyValueMapping<Integer> mapping = new KeyValueMapping<>();
  1318. KeyValueIterator<Integer> keyValueIterator = map.tableKeyValueIterator();
  1319.  
  1320. while (keyValueIterator.hasNextKeyValuePair()) {
  1321. keyValueIterator.nextKeyValuePair(mapping);
  1322. }
  1323.  
  1324. endTime = System.currentTimeMillis();
  1325. totalTime += endTime - startTime;
  1326.  
  1327. System.out.println(
  1328. "Key/value iteration in " + (endTime - startTime) +
  1329. " milliseconds.");
  1330.  
  1331. // get().
  1332. startTime = System.currentTimeMillis();
  1333.  
  1334. for (Integer i : testArray) {
  1335. map.get(i);
  1336. }
  1337.  
  1338. endTime = System.currentTimeMillis();
  1339. totalTime += endTime - startTime;
  1340.  
  1341. System.out.println(
  1342. "get() in " + (endTime - startTime) + " milliseconds.");
  1343.  
  1344. // containsKey().
  1345. startTime = System.currentTimeMillis();
  1346.  
  1347. for (Integer i : testArray) {
  1348. map.containsKey(i);
  1349. }
  1350.  
  1351. endTime = System.currentTimeMillis();
  1352. totalTime += endTime - startTime;
  1353.  
  1354. System.out.println(
  1355. "contains() in " + (endTime - startTime) + " milliseconds.");
  1356.  
  1357. // remove().
  1358. startTime = System.currentTimeMillis();
  1359.  
  1360. for (Integer i : testArray) {
  1361. map.remove(i);
  1362. }
  1363.  
  1364. endTime = System.currentTimeMillis();
  1365. totalTime += endTime - startTime;
  1366.  
  1367. System.out.println(
  1368. "remove() in " + (endTime - startTime) + " milliseconds.");
  1369. System.out.println("Total time: " + totalTime + " milliseconds.");
  1370. }
  1371.  
  1372. private static void benchmarkMap(Map<Integer, Integer> map,
  1373. Integer[] testArray) {
  1374. System.out.println("--- " + map.getClass().getSimpleName() + " ---");
  1375.  
  1376. long startTime;
  1377. long endTime;
  1378. long totalTime = 0L;
  1379.  
  1380. // put().
  1381. startTime = System.currentTimeMillis();
  1382.  
  1383. for (Integer i : testArray) {
  1384. map.put(i, i);
  1385. }
  1386.  
  1387. endTime = System.currentTimeMillis();
  1388. totalTime += endTime - startTime;
  1389.  
  1390. System.out.println(
  1391. "put() in " + (endTime - startTime) + " milliseconds.");
  1392.  
  1393. // Key iteration.
  1394. startTime = System.currentTimeMillis();
  1395.  
  1396. for (Integer i : map.keySet()) {
  1397.  
  1398. }
  1399.  
  1400. endTime = System.currentTimeMillis();
  1401. totalTime += endTime - startTime;
  1402.  
  1403. System.out.println(
  1404. "keySet().iterator() in " + (endTime - startTime) +
  1405. " milliseconds.");
  1406.  
  1407. // Entry set iteration.
  1408. startTime = System.currentTimeMillis();
  1409.  
  1410. for (Map.Entry<Integer, Integer> e : map.entrySet()) {
  1411.  
  1412. }
  1413.  
  1414. endTime = System.currentTimeMillis();
  1415. totalTime += endTime - startTime;
  1416.  
  1417. System.out.println(
  1418. "entrySet().iterator() in " + (endTime - startTime) +
  1419. " milliseconds.");
  1420.  
  1421. // get().
  1422. startTime = System.currentTimeMillis();
  1423.  
  1424. for (Integer i : testArray) {
  1425. map.get(i);
  1426. }
  1427.  
  1428. endTime = System.currentTimeMillis();
  1429. totalTime += endTime - startTime;
  1430.  
  1431. System.out.println(
  1432. "get() in " + (endTime - startTime) + " milliseconds.");
  1433.  
  1434. // containsKey().
  1435. startTime = System.currentTimeMillis();
  1436.  
  1437. for (int i = MINIMUM_KEY; i <= MAXIMUM_KEY; ++i) {
  1438. map.containsKey(i);
  1439. }
  1440.  
  1441. endTime = System.currentTimeMillis();
  1442. totalTime += endTime - startTime;
  1443.  
  1444. System.out.println(
  1445. "containsKey() in " + (endTime - startTime) + " milliseconds.");
  1446.  
  1447. // remove().
  1448. startTime = System.currentTimeMillis();
  1449.  
  1450. for (Integer i : testArray) {
  1451. map.remove(i);
  1452. }
  1453.  
  1454. endTime = System.currentTimeMillis();
  1455. totalTime += endTime - startTime;
  1456.  
  1457. System.out.println(
  1458. "remove() in " + (endTime - startTime) + " milliseconds.");
  1459. System.out.println("Total time: " + totalTime + " milliseconds.");
  1460. }
  1461.  
  1462. private static void warmup() {
  1463. System.out.println("Warming up...");
  1464. VanEmdeBoasTreeIntMap<Integer> vebMap =
  1465. new VanEmdeBoasTreeIntMap<>(MINIMUM_KEY, MAXIMUM_KEY);
  1466.  
  1467. Map<Integer, Integer> treeMap = new TreeMap<>();
  1468. Map<Integer, Integer> hashMap = new HashMap<>();
  1469.  
  1470. Integer[] randomIntegerArray =
  1471. createRandomIntegerArray(INTEGER_ARRAY_LENGTH,
  1472. MINIMUM_KEY,
  1473. MAXIMUM_KEY);
  1474.  
  1475. for (Integer i : randomIntegerArray) {
  1476. vebMap.put(i, i);
  1477. treeMap.put(i, i);
  1478. hashMap.put(i, i);
  1479. }
  1480.  
  1481. for (Integer i : randomIntegerArray) {
  1482. vebMap.containsKey(i);
  1483. treeMap.containsKey(i);
  1484. hashMap.containsKey(i);
  1485. }
  1486.  
  1487. for (Map.Entry<Integer, Integer> e : treeMap.entrySet()) {
  1488.  
  1489. }
  1490.  
  1491. for (Integer i : treeMap.keySet()) {
  1492.  
  1493. }
  1494.  
  1495. for (Map.Entry<Integer, Integer> e : hashMap.entrySet()) {
  1496.  
  1497. }
  1498.  
  1499. for (Integer i : hashMap.keySet()) {
  1500.  
  1501. }
  1502.  
  1503. KeyIterator keyIterator = vebMap.treeKeyIterator();
  1504.  
  1505. while (keyIterator.hasNextKey()) {
  1506. keyIterator.nextKey();
  1507. }
  1508.  
  1509. keyIterator = vebMap.tableKeyIterator();
  1510.  
  1511. while (keyIterator.hasNextKey()) {
  1512. keyIterator.nextKey();
  1513. }
  1514.  
  1515. KeyValueMapping<Integer> mapping = new KeyValueMapping<>();
  1516. KeyValueIterator<Integer> keyValueIterator =
  1517. vebMap.treeKeyValueIterator();
  1518.  
  1519. while (keyValueIterator.hasNextKeyValuePair()) {
  1520. keyValueIterator.nextKeyValuePair(mapping);
  1521. }
  1522.  
  1523. keyValueIterator =
  1524. vebMap.tableKeyValueIterator();
  1525.  
  1526. while (keyValueIterator.hasNextKeyValuePair()) {
  1527. keyValueIterator.nextKeyValuePair(mapping);
  1528. }
  1529.  
  1530. for (Integer i : randomIntegerArray) {
  1531. vebMap.remove(i);
  1532. treeMap.remove(i);
  1533. hashMap.remove(i);
  1534. }
  1535.  
  1536. System.out.println("Warming up done!");
  1537. }
  1538.  
  1539. private static Integer[] createRandomIntegerArray(int length,
  1540. int minimumKey,
  1541. int maximumKey) {
  1542. Integer[] array = new Integer[length];
  1543. int rangeLength = maximumKey - minimumKey + 1;
  1544.  
  1545. for (int i = 0; i < length; ++i) {
  1546. array[i] = RANDOM.nextInt(rangeLength) + minimumKey;
  1547. }
  1548.  
  1549. return array;
  1550. }
  1551. }
  1552.  
  1553. Seed = 1513196888667
  1554. Warming up...
  1555. Warming up done!
  1556.  
  1557. --- TreeMap ---
  1558. put() in 2222 milliseconds.
  1559. keySet().iterator() in 166 milliseconds.
  1560. entrySet().iterator() in 160 milliseconds.
  1561. get() in 2148 milliseconds.
  1562. containsKey() in 424 milliseconds.
  1563. remove() in 2131 milliseconds.
  1564. Total time: 7251 milliseconds.
  1565.  
  1566. --- HashMap ---
  1567. put() in 563 milliseconds.
  1568. keySet().iterator() in 160 milliseconds.
  1569. entrySet().iterator() in 114 milliseconds.
  1570. get() in 169 milliseconds.
  1571. containsKey() in 190 milliseconds.
  1572. remove() in 118 milliseconds.
  1573. Total time: 1314 milliseconds.
  1574.  
  1575. --- VanEmdeBoasTreeIntMap ---
  1576. Constructed a van Emde Boas tree in 1698 milliseconds.
  1577. put() in 754 milliseconds.
  1578. Key iteration in 32 milliseconds.
  1579. Key/value iteration in 32 milliseconds.
  1580. get() in 40 milliseconds.
  1581. contains() in 39 milliseconds.
  1582. remove() in 804 milliseconds.
  1583. Total time: 3399 milliseconds.
Add Comment
Please, Sign In to add comment