1 19 package bak.pcj.map; 20 21 import bak.pcj.IntCollection; 22 import bak.pcj.AbstractIntCollection; 23 import bak.pcj.FloatIterator; 24 import bak.pcj.IntIterator; 25 import bak.pcj.AbstractFloatCollection; 26 import bak.pcj.set.AbstractFloatSet; 27 import bak.pcj.set.FloatSet; 28 import bak.pcj.hash.FloatHashFunction; 29 import bak.pcj.hash.DefaultFloatHashFunction; 30 import bak.pcj.util.Exceptions; 31 32 import java.io.Serializable ; 33 import java.io.IOException ; 34 import java.io.ObjectInputStream ; 35 import java.io.ObjectOutputStream ; 36 37 48 public class FloatKeyIntOpenHashMap extends AbstractFloatKeyIntMap implements FloatKeyIntMap, Cloneable , Serializable { 49 50 51 private static final int GROWTH_POLICY_RELATIVE = 0; 52 53 54 private static final int GROWTH_POLICY_ABSOLUTE = 1; 55 56 61 private static final int DEFAULT_GROWTH_POLICY = GROWTH_POLICY_RELATIVE; 62 63 64 public static final double DEFAULT_GROWTH_FACTOR = 1.0; 65 66 67 public static final int DEFAULT_GROWTH_CHUNK = 10; 68 69 70 public static final int DEFAULT_CAPACITY = 11; 71 72 73 public static final double DEFAULT_LOAD_FACTOR = 0.75; 74 75 79 private FloatHashFunction keyhash; 80 81 85 private int size; 86 87 92 private transient float[] keys; 93 94 99 private transient int[] values; 100 101 102 private transient byte[] states; 103 104 private static final byte EMPTY = 0; 105 private static final byte OCCUPIED = 1; 106 private static final byte REMOVED = 2; 107 108 109 private transient int used; 110 111 115 private int growthPolicy; 116 117 122 private double growthFactor; 123 124 129 private int growthChunk; 130 131 135 private double loadFactor; 136 137 141 private int expandAt; 142 143 144 private transient FloatSet ckeys; 145 146 147 private transient IntCollection cvalues; 148 149 150 private transient boolean hasLastValue; 151 152 153 private transient int lastValue; 154 155 private FloatKeyIntOpenHashMap(FloatHashFunction keyhash, int capacity, int growthPolicy, double growthFactor, int growthChunk, double loadFactor) { 156 if (keyhash == null) 157 Exceptions.nullArgument("hash function"); 158 if (capacity < 0) 159 Exceptions.negativeArgument("capacity", String.valueOf(capacity)); 160 if (growthFactor <= 0.0) 161 Exceptions.negativeOrZeroArgument("growthFactor", String.valueOf(growthFactor)); 162 if (growthChunk <= 0) 163 Exceptions.negativeOrZeroArgument("growthChunk", String.valueOf(growthChunk)); 164 if (loadFactor <= 0.0) 165 Exceptions.negativeOrZeroArgument("loadFactor", String.valueOf(loadFactor)); 166 this.keyhash = keyhash; 167 capacity = bak.pcj.hash.Primes.nextPrime(capacity); 168 keys = new float[capacity]; 169 values = new int[capacity]; 170 this.states = new byte[capacity]; 171 size = 0; 172 expandAt = (int)Math.round(loadFactor*capacity); 173 this.used = 0; 174 this.growthPolicy = growthPolicy; 175 this.growthFactor = growthFactor; 176 this.growthChunk = growthChunk; 177 this.loadFactor = loadFactor; 178 hasLastValue = false; 179 } 180 181 private FloatKeyIntOpenHashMap(int capacity, int growthPolicy, double growthFactor, int growthChunk, double loadFactor) { 182 this(DefaultFloatHashFunction.INSTANCE, capacity, growthPolicy, growthFactor, growthChunk, loadFactor); 183 } 184 185 189 public FloatKeyIntOpenHashMap() { 190 this(DEFAULT_CAPACITY); 191 } 192 193 202 public FloatKeyIntOpenHashMap(FloatKeyIntMap map) { 203 this(); 204 putAll(map); 205 } 206 207 217 public FloatKeyIntOpenHashMap(int capacity) { 218 this(capacity, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, DEFAULT_LOAD_FACTOR); 219 } 220 221 232 public FloatKeyIntOpenHashMap(double loadFactor) { 233 this(DEFAULT_CAPACITY, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, loadFactor); 234 } 235 236 250 public FloatKeyIntOpenHashMap(int capacity, double loadFactor) { 251 this(capacity, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, loadFactor); 252 } 253 254 277 public FloatKeyIntOpenHashMap(int capacity, double loadFactor, double growthFactor) { 278 this(capacity, GROWTH_POLICY_RELATIVE, growthFactor, DEFAULT_GROWTH_CHUNK, loadFactor); 279 } 280 281 304 public FloatKeyIntOpenHashMap(int capacity, double loadFactor, int growthChunk) { 305 this(capacity, GROWTH_POLICY_ABSOLUTE, DEFAULT_GROWTH_FACTOR, growthChunk, loadFactor); 306 } 307 308 312 322 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash) { 323 this(keyhash, DEFAULT_CAPACITY, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, DEFAULT_LOAD_FACTOR); 324 } 325 326 342 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash, int capacity) { 343 this(keyhash, capacity, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, DEFAULT_LOAD_FACTOR); 344 } 345 346 363 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash, double loadFactor) { 364 this(keyhash, DEFAULT_CAPACITY, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, loadFactor); 365 } 366 367 387 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash, int capacity, double loadFactor) { 388 this(keyhash, capacity, DEFAULT_GROWTH_POLICY, DEFAULT_GROWTH_FACTOR, DEFAULT_GROWTH_CHUNK, loadFactor); 389 } 390 391 420 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash, int capacity, double loadFactor, double growthFactor) { 421 this(keyhash, capacity, GROWTH_POLICY_RELATIVE, growthFactor, DEFAULT_GROWTH_CHUNK, loadFactor); 422 } 423 424 453 public FloatKeyIntOpenHashMap(FloatHashFunction keyhash, int capacity, double loadFactor, int growthChunk) { 454 this(keyhash, capacity, GROWTH_POLICY_ABSOLUTE, DEFAULT_GROWTH_FACTOR, growthChunk, loadFactor); 455 } 456 457 461 private void ensureCapacity(int elements) { 462 if (elements >= expandAt) { 463 int newcapacity; 464 if (growthPolicy == GROWTH_POLICY_RELATIVE) 465 newcapacity = (int)(keys.length * (1.0 + growthFactor)); 466 else 467 newcapacity = keys.length + growthChunk; 468 if (newcapacity*loadFactor < elements) 469 newcapacity = (int)Math.round(((double)elements/loadFactor)); 470 newcapacity = bak.pcj.hash.Primes.nextPrime(newcapacity); 471 expandAt = (int)Math.round(loadFactor*newcapacity); 472 473 float[] newkeys = new float[newcapacity]; 474 int[] newvalues = new int[newcapacity]; 475 byte[] newstates = new byte[newcapacity]; 476 477 used = 0; 478 for (int i = 0; i < keys.length; i++) { 480 if (states[i] == OCCUPIED) { 481 used++; 482 float k = keys[i]; 483 int v = values[i]; 484 int h = Math.abs(keyhash.hash(k)); 486 int n = h % newcapacity; 487 if (newstates[n] == OCCUPIED) { 488 int c = 1 + (h % (newcapacity - 2)); 490 for (;;) { 491 n -= c; 492 if (n < 0) 493 n += newcapacity; 494 if (newstates[n] == EMPTY) 495 break; 496 } 497 } 498 newstates[n] = OCCUPIED; 499 newvalues[n] = v; 500 newkeys[n] = k; 501 } 502 } 503 504 keys = newkeys; 505 values = newvalues; 506 states = newstates; 507 } 508 } 509 510 514 public FloatSet keySet() { 515 if (ckeys == null) 516 ckeys = new KeySet(); 517 return ckeys; 518 } 519 520 public int lget() { 521 if (!hasLastValue) 522 Exceptions.noLastElement(); 523 return lastValue; 524 } 525 526 public int put(float key, int value) { 527 int result; 528 529 int h = Math.abs(keyhash.hash(key)); 531 int i = h % keys.length; 532 if (states[i] == OCCUPIED) { 533 if (keys[i] == key) { 534 int oldValue = values[i]; 535 values[i] = value; 536 return oldValue; 537 } 538 int c = 1 + (h % (keys.length - 2)); 540 for (;;) { 541 i -= c; 542 if (i < 0) 543 i += keys.length; 544 if (states[i] == EMPTY || states[i] == REMOVED) 546 break; 547 if (states[i] == OCCUPIED && keys[i] == key) { 548 int oldValue = values[i]; 549 values[i] = value; 550 return oldValue; 551 } 552 } 553 } 554 if (states[i] == EMPTY) 555 used++; 556 states[i] = OCCUPIED; 557 keys[i] = key; 558 values[i] = value; 559 size++; 560 ensureCapacity(used); 561 return MapDefaults.defaultInt(); 562 } 563 564 public IntCollection values() { 565 if (cvalues == null) 566 cvalues = new ValueCollection(); 567 return cvalues; 568 } 569 570 577 public Object clone() { 578 try { 579 FloatKeyIntOpenHashMap c = (FloatKeyIntOpenHashMap)super.clone(); 580 c.keys = new float[keys.length]; 581 System.arraycopy(keys, 0, c.keys, 0, keys.length); 582 c.values = new int[values.length]; 583 System.arraycopy(values, 0, c.values, 0, values.length); 584 c.states = new byte[states.length]; 585 System.arraycopy(states, 0, c.states, 0, states.length); 586 c.cvalues = null; 588 c.ckeys = null; 589 return c; 590 } catch (CloneNotSupportedException e) { 591 Exceptions.cloning(); return null; 592 } 593 } 594 595 public FloatKeyIntMapIterator entries() { 596 return new FloatKeyIntMapIterator() { 597 int nextEntry = nextEntry(0); 598 int lastEntry = -1; 599 600 int nextEntry(int index) { 601 while (index < keys.length && states[index] != OCCUPIED) 602 index++; 603 return index; 604 } 605 606 public boolean hasNext() { 607 return nextEntry < keys.length; 608 } 609 610 public void next() { 611 if (!hasNext()) 612 Exceptions.endOfIterator(); 613 lastEntry = nextEntry; 614 nextEntry = nextEntry(nextEntry+1); 615 } 616 617 public void remove() { 618 if (lastEntry == -1) 619 Exceptions.noElementToRemove(); 620 states[lastEntry] = REMOVED; 621 size--; 622 lastEntry = -1; 623 } 624 625 public float getKey() { 626 if (lastEntry == -1) 627 Exceptions.noElementToGet(); 628 return keys[lastEntry]; 629 } 630 631 public int getValue() { 632 if (lastEntry == -1) 633 Exceptions.noElementToGet(); 634 return values[lastEntry]; 635 } 636 }; 637 } 638 639 private class KeySet extends AbstractFloatSet { 640 641 public void clear() 642 { FloatKeyIntOpenHashMap.this.clear(); } 643 644 public boolean contains(float v) { 645 return containsKey(v); 646 } 647 648 public FloatIterator iterator() { 649 return new FloatIterator() { 650 int nextEntry = nextEntry(0); 651 int lastEntry = -1; 652 653 int nextEntry(int index) { 654 while (index < keys.length && states[index] != OCCUPIED) 655 index++; 656 return index; 657 } 658 659 public boolean hasNext() { 660 return nextEntry < keys.length; 661 } 662 663 public float next() { 664 if (!hasNext()) 665 Exceptions.endOfIterator(); 666 lastEntry = nextEntry; 667 nextEntry = nextEntry(nextEntry+1); 668 return keys[lastEntry]; 669 } 670 671 public void remove() { 672 if (lastEntry == -1) 673 Exceptions.noElementToRemove(); 674 states[lastEntry] = REMOVED; 675 size--; 676 lastEntry = -1; 677 } 678 }; 679 } 680 681 public boolean remove(float v) { 682 boolean result = containsKey(v); 683 if (result) 684 FloatKeyIntOpenHashMap.this.remove(v); 685 return result; 686 } 687 688 public int size() 689 { return size; } 690 691 } 692 693 694 private class ValueCollection extends AbstractIntCollection { 695 696 public void clear() 697 { FloatKeyIntOpenHashMap.this.clear(); } 698 699 public boolean contains(int v) { 700 return containsValue(v); 701 } 702 703 public IntIterator iterator() { 704 return new IntIterator() { 705 int nextEntry = nextEntry(0); 706 int lastEntry = -1; 707 708 int nextEntry(int index) { 709 while (index < keys.length && states[index] != OCCUPIED) 710 index++; 711 return index; 712 } 713 714 public boolean hasNext() { 715 return nextEntry < keys.length; 716 } 717 718 public int next() { 719 if (!hasNext()) 720 Exceptions.endOfIterator(); 721 lastEntry = nextEntry; 722 nextEntry = nextEntry(nextEntry+1); 723 return values[lastEntry]; 724 } 725 726 public void remove() { 727 if (lastEntry == -1) 728 Exceptions.noElementToRemove(); 729 states[lastEntry] = REMOVED; 730 size--; 731 lastEntry = -1; 732 } 733 }; 734 } 735 736 public int size() 737 { return size; } 738 739 } 740 741 745 public void clear() { 746 java.util.Arrays.fill(states, EMPTY); 747 size = 0; 748 used = 0; 749 } 750 751 public boolean containsKey(float key) { 752 int h = Math.abs(keyhash.hash(key)); 753 int i = h % keys.length; 754 if (states[i] != EMPTY) { 755 if (states[i] == OCCUPIED && keys[i] == key) { 756 hasLastValue = true; 757 lastValue = values[i]; 758 return true; 759 } 760 762 int c = 1 + (h % (keys.length - 2)); 763 for (;;) { 764 i -= c; 765 if (i < 0) 766 i += keys.length; 767 if (states[i] == EMPTY) { 768 hasLastValue = false; 769 return false; 770 } 771 if (states[i] == OCCUPIED && keys[i] == key) { 772 hasLastValue = true; 773 lastValue = values[i]; 774 return true; 775 } 776 } 777 } 778 hasLastValue = false; 779 return false; 780 } 781 782 public boolean containsValue(int value) { 783 for (int i = 0; i < states.length; i++) 784 if (states[i] == OCCUPIED && values[i] == value) 785 return true; 786 return false; 787 } 788 789 public int get(float key) { 790 int h = Math.abs(keyhash.hash(key)); 791 int i = h % keys.length; 792 if (states[i] != EMPTY) { 793 if (states[i] == OCCUPIED && keys[i] == key) 794 return values[i]; 795 797 int c = 1 + (h % (keys.length - 2)); 798 for (;;) { 799 i -= c; 800 if (i < 0) 801 i += keys.length; 802 if (states[i] == EMPTY) 803 return MapDefaults.defaultInt(); 804 if (states[i] == OCCUPIED && keys[i] == key) 805 return values[i]; 806 } 807 } 808 return MapDefaults.defaultInt(); 809 } 810 811 public boolean isEmpty() 812 { return size == 0; } 813 814 public int remove(float key) { 815 int h = Math.abs(keyhash.hash(key)); 816 int i = h % keys.length; 817 if (states[i] != EMPTY) { 818 if (states[i] == OCCUPIED && keys[i] == key) { 819 int oldValue = values[i]; 820 states[i] = REMOVED; 821 size--; 822 return oldValue; 823 } 824 int c = 1 + (h % (keys.length - 2)); 826 for (;;) { 827 i -= c; 828 if (i < 0) 829 i += keys.length; 830 if (states[i] == EMPTY) { 831 return MapDefaults.defaultInt(); 832 } 833 if (states[i] == OCCUPIED && keys[i] == key) { 834 int oldValue = values[i]; 835 states[i] = REMOVED; 836 size--; 837 return oldValue; 838 } 839 } 840 } 841 return MapDefaults.defaultInt(); 842 } 843 844 public int size() 845 { return size; } 846 847 public int tget(float key) { 848 int h = Math.abs(keyhash.hash(key)); 849 int i = h % keys.length; 850 if (states[i] != EMPTY) { 851 if (states[i] == OCCUPIED && keys[i] == key) 852 return values[i]; 853 855 int c = 1 + (h % (keys.length - 2)); 856 for (;;) { 857 i -= c; 858 if (i < 0) 859 i += keys.length; 860 if (states[i] == EMPTY) 861 Exceptions.noSuchMapping(String.valueOf(key)); 862 if (states[i] == OCCUPIED && keys[i] == key) 863 return values[i]; 864 } 865 } 866 Exceptions.noSuchMapping(String.valueOf(key)); throw new RuntimeException (); 867 } 868 869 873 880 private void writeObject(ObjectOutputStream s) throws IOException { 881 s.defaultWriteObject(); 882 s.writeInt(keys.length); 883 FloatKeyIntMapIterator i = entries(); 884 while (i.hasNext()) { 885 i.next(); 886 s.writeFloat(i.getKey()); 887 s.writeInt(i.getValue()); 888 } 889 } 890 891 894 private void readObject(ObjectInputStream s) throws IOException , ClassNotFoundException { 895 s.defaultReadObject(); 896 keys = new float[s.readInt()]; 897 states = new byte[keys.length]; 898 values = new int[keys.length]; 899 used = size; 900 901 for (int n = 0; n < size; n++) { 902 float key = s.readFloat(); 903 int value = s.readInt(); 904 905 int h = Math.abs(keyhash.hash(key)); 907 int i = h % keys.length; 908 if (states[i] != EMPTY) { 909 int c = 1 + (h % (keys.length - 2)); 911 for (;;) { 912 i -= c; 913 if (i < 0) 914 i += keys.length; 915 if (states[i] == EMPTY) 916 break; 917 } 918 } 919 states[i] = OCCUPIED; 920 keys[i] = key; 921 values[i] = value; 922 } 923 } 924 925 } | Popular Tags |