1 16 package org.apache.commons.collections.map; 17 18 import java.io.IOException ; 19 import java.io.ObjectInputStream ; 20 import java.io.ObjectOutputStream ; 21 import java.io.Serializable ; 22 import java.util.AbstractCollection ; 23 import java.util.AbstractSet ; 24 import java.util.Collection ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 import java.util.NoSuchElementException ; 28 import java.util.Set ; 29 30 import org.apache.commons.collections.IterableMap; 31 import org.apache.commons.collections.MapIterator; 32 import org.apache.commons.collections.ResettableIterator; 33 import org.apache.commons.collections.iterators.EmptyIterator; 34 import org.apache.commons.collections.iterators.EmptyMapIterator; 35 36 68 public class Flat3Map implements IterableMap, Serializable , Cloneable { 69 70 71 private static final long serialVersionUID = -6701087419741928296L; 72 73 74 private transient int size; 75 76 private transient int hash1; 77 78 private transient int hash2; 79 80 private transient int hash3; 81 82 private transient Object key1; 83 84 private transient Object key2; 85 86 private transient Object key3; 87 88 private transient Object value1; 89 90 private transient Object value2; 91 92 private transient Object value3; 93 94 private transient AbstractHashedMap delegateMap; 95 96 99 public Flat3Map() { 100 super(); 101 } 102 103 109 public Flat3Map(Map map) { 110 super(); 111 putAll(map); 112 } 113 114 121 public Object get(Object key) { 122 if (delegateMap != null) { 123 return delegateMap.get(key); 124 } 125 if (key == null) { 126 switch (size) { 127 case 3: 129 if (key3 == null) return value3; 130 case 2: 131 if (key2 == null) return value2; 132 case 1: 133 if (key1 == null) return value1; 134 } 135 } else { 136 if (size > 0) { 137 int hashCode = key.hashCode(); 138 switch (size) { 139 case 3: 141 if (hash3 == hashCode && key.equals(key3)) return value3; 142 case 2: 143 if (hash2 == hashCode && key.equals(key2)) return value2; 144 case 1: 145 if (hash1 == hashCode && key.equals(key1)) return value1; 146 } 147 } 148 } 149 return null; 150 } 151 152 157 public int size() { 158 if (delegateMap != null) { 159 return delegateMap.size(); 160 } 161 return size; 162 } 163 164 169 public boolean isEmpty() { 170 return (size() == 0); 171 } 172 173 180 public boolean containsKey(Object key) { 181 if (delegateMap != null) { 182 return delegateMap.containsKey(key); 183 } 184 if (key == null) { 185 switch (size) { case 3: 187 if (key3 == null) return true; 188 case 2: 189 if (key2 == null) return true; 190 case 1: 191 if (key1 == null) return true; 192 } 193 } else { 194 if (size > 0) { 195 int hashCode = key.hashCode(); 196 switch (size) { case 3: 198 if (hash3 == hashCode && key.equals(key3)) return true; 199 case 2: 200 if (hash2 == hashCode && key.equals(key2)) return true; 201 case 1: 202 if (hash1 == hashCode && key.equals(key1)) return true; 203 } 204 } 205 } 206 return false; 207 } 208 209 215 public boolean containsValue(Object value) { 216 if (delegateMap != null) { 217 return delegateMap.containsValue(value); 218 } 219 if (value == null) { switch (size) { 221 case 3: 222 if (value3 == null) return true; 223 case 2: 224 if (value2 == null) return true; 225 case 1: 226 if (value1 == null) return true; 227 } 228 } else { 229 switch (size) { case 3: 231 if (value.equals(value3)) return true; 232 case 2: 233 if (value.equals(value2)) return true; 234 case 1: 235 if (value.equals(value1)) return true; 236 } 237 } 238 return false; 239 } 240 241 249 public Object put(Object key, Object value) { 250 if (delegateMap != null) { 251 return delegateMap.put(key, value); 252 } 253 if (key == null) { 255 switch (size) { case 3: 257 if (key3 == null) { 258 Object old = value3; 259 value3 = value; 260 return old; 261 } 262 case 2: 263 if (key2 == null) { 264 Object old = value2; 265 value2 = value; 266 return old; 267 } 268 case 1: 269 if (key1 == null) { 270 Object old = value1; 271 value1 = value; 272 return old; 273 } 274 } 275 } else { 276 if (size > 0) { 277 int hashCode = key.hashCode(); 278 switch (size) { case 3: 280 if (hash3 == hashCode && key.equals(key3)) { 281 Object old = value3; 282 value3 = value; 283 return old; 284 } 285 case 2: 286 if (hash2 == hashCode && key.equals(key2)) { 287 Object old = value2; 288 value2 = value; 289 return old; 290 } 291 case 1: 292 if (hash1 == hashCode && key.equals(key1)) { 293 Object old = value1; 294 value1 = value; 295 return old; 296 } 297 } 298 } 299 } 300 301 switch (size) { 303 default: 304 convertToMap(); 305 delegateMap.put(key, value); 306 return null; 307 case 2: 308 hash3 = (key == null ? 0 : key.hashCode()); 309 key3 = key; 310 value3 = value; 311 break; 312 case 1: 313 hash2 = (key == null ? 0 : key.hashCode()); 314 key2 = key; 315 value2 = value; 316 break; 317 case 0: 318 hash1 = (key == null ? 0 : key.hashCode()); 319 key1 = key; 320 value1 = value; 321 break; 322 } 323 size++; 324 return null; 325 } 326 327 333 public void putAll(Map map) { 334 int size = map.size(); 335 if (size == 0) { 336 return; 337 } 338 if (delegateMap != null) { 339 delegateMap.putAll(map); 340 return; 341 } 342 if (size < 4) { 343 for (Iterator it = map.entrySet().iterator(); it.hasNext();) { 344 Map.Entry entry = (Map.Entry ) it.next(); 345 put(entry.getKey(), entry.getValue()); 346 } 347 } else { 348 convertToMap(); 349 delegateMap.putAll(map); 350 } 351 } 352 353 356 private void convertToMap() { 357 delegateMap = createDelegateMap(); 358 switch (size) { case 3: 360 delegateMap.put(key3, value3); 361 case 2: 362 delegateMap.put(key2, value2); 363 case 1: 364 delegateMap.put(key1, value1); 365 } 366 367 size = 0; 368 hash1 = hash2 = hash3 = 0; 369 key1 = key2 = key3 = null; 370 value1 = value2 = value3 = null; 371 } 372 373 383 protected AbstractHashedMap createDelegateMap() { 384 return new HashedMap(); 385 } 386 387 393 public Object remove(Object key) { 394 if (delegateMap != null) { 395 return delegateMap.remove(key); 396 } 397 if (size == 0) { 398 return null; 399 } 400 if (key == null) { 401 switch (size) { case 3: 403 if (key3 == null) { 404 Object old = value3; 405 hash3 = 0; 406 key3 = null; 407 value3 = null; 408 size = 2; 409 return old; 410 } 411 if (key2 == null) { 412 Object old = value3; 413 hash2 = hash3; 414 key2 = key3; 415 value2 = value3; 416 hash3 = 0; 417 key3 = null; 418 value3 = null; 419 size = 2; 420 return old; 421 } 422 if (key1 == null) { 423 Object old = value3; 424 hash1 = hash3; 425 key1 = key3; 426 value1 = value3; 427 hash3 = 0; 428 key3 = null; 429 value3 = null; 430 size = 2; 431 return old; 432 } 433 return null; 434 case 2: 435 if (key2 == null) { 436 Object old = value2; 437 hash2 = 0; 438 key2 = null; 439 value2 = null; 440 size = 1; 441 return old; 442 } 443 if (key1 == null) { 444 Object old = value2; 445 hash1 = hash2; 446 key1 = key2; 447 value1 = value2; 448 hash2 = 0; 449 key2 = null; 450 value2 = null; 451 size = 1; 452 return old; 453 } 454 return null; 455 case 1: 456 if (key1 == null) { 457 Object old = value1; 458 hash1 = 0; 459 key1 = null; 460 value1 = null; 461 size = 0; 462 return old; 463 } 464 } 465 } else { 466 if (size > 0) { 467 int hashCode = key.hashCode(); 468 switch (size) { case 3: 470 if (hash3 == hashCode && key.equals(key3)) { 471 Object old = value3; 472 hash3 = 0; 473 key3 = null; 474 value3 = null; 475 size = 2; 476 return old; 477 } 478 if (hash2 == hashCode && key.equals(key2)) { 479 Object old = value3; 480 hash2 = hash3; 481 key2 = key3; 482 value2 = value3; 483 hash3 = 0; 484 key3 = null; 485 value3 = null; 486 size = 2; 487 return old; 488 } 489 if (hash1 == hashCode && key.equals(key1)) { 490 Object old = value3; 491 hash1 = hash3; 492 key1 = key3; 493 value1 = value3; 494 hash3 = 0; 495 key3 = null; 496 value3 = null; 497 size = 2; 498 return old; 499 } 500 return null; 501 case 2: 502 if (hash2 == hashCode && key.equals(key2)) { 503 Object old = value2; 504 hash2 = 0; 505 key2 = null; 506 value2 = null; 507 size = 1; 508 return old; 509 } 510 if (hash1 == hashCode && key.equals(key1)) { 511 Object old = value2; 512 hash1 = hash2; 513 key1 = key2; 514 value1 = value2; 515 hash2 = 0; 516 key2 = null; 517 value2 = null; 518 size = 1; 519 return old; 520 } 521 return null; 522 case 1: 523 if (hash1 == hashCode && key.equals(key1)) { 524 Object old = value1; 525 hash1 = 0; 526 key1 = null; 527 value1 = null; 528 size = 0; 529 return old; 530 } 531 } 532 } 533 } 534 return null; 535 } 536 537 541 public void clear() { 542 if (delegateMap != null) { 543 delegateMap.clear(); delegateMap = null; } else { 546 size = 0; 547 hash1 = hash2 = hash3 = 0; 548 key1 = key2 = key3 = null; 549 value1 = value2 = value3 = null; 550 } 551 } 552 553 565 public MapIterator mapIterator() { 566 if (delegateMap != null) { 567 return delegateMap.mapIterator(); 568 } 569 if (size == 0) { 570 return EmptyMapIterator.INSTANCE; 571 } 572 return new FlatMapIterator(this); 573 } 574 575 578 static class FlatMapIterator implements MapIterator, ResettableIterator { 579 private final Flat3Map parent; 580 private int nextIndex = 0; 581 private boolean canRemove = false; 582 583 FlatMapIterator(Flat3Map parent) { 584 super(); 585 this.parent = parent; 586 } 587 588 public boolean hasNext() { 589 return (nextIndex < parent.size); 590 } 591 592 public Object next() { 593 if (hasNext() == false) { 594 throw new NoSuchElementException (AbstractHashedMap.NO_NEXT_ENTRY); 595 } 596 canRemove = true; 597 nextIndex++; 598 return getKey(); 599 } 600 601 public void remove() { 602 if (canRemove == false) { 603 throw new IllegalStateException (AbstractHashedMap.REMOVE_INVALID); 604 } 605 parent.remove(getKey()); 606 nextIndex--; 607 canRemove = false; 608 } 609 610 public Object getKey() { 611 if (canRemove == false) { 612 throw new IllegalStateException (AbstractHashedMap.GETKEY_INVALID); 613 } 614 switch (nextIndex) { 615 case 3: 616 return parent.key3; 617 case 2: 618 return parent.key2; 619 case 1: 620 return parent.key1; 621 } 622 throw new IllegalStateException ("Invalid map index"); 623 } 624 625 public Object getValue() { 626 if (canRemove == false) { 627 throw new IllegalStateException (AbstractHashedMap.GETVALUE_INVALID); 628 } 629 switch (nextIndex) { 630 case 3: 631 return parent.value3; 632 case 2: 633 return parent.value2; 634 case 1: 635 return parent.value1; 636 } 637 throw new IllegalStateException ("Invalid map index"); 638 } 639 640 public Object setValue(Object value) { 641 if (canRemove == false) { 642 throw new IllegalStateException (AbstractHashedMap.SETVALUE_INVALID); 643 } 644 Object old = getValue(); 645 switch (nextIndex) { 646 case 3: 647 parent.value3 = value; 648 case 2: 649 parent.value2 = value; 650 case 1: 651 parent.value1 = value; 652 } 653 return old; 654 } 655 656 public void reset() { 657 nextIndex = 0; 658 canRemove = false; 659 } 660 661 public String toString() { 662 if (canRemove) { 663 return "Iterator[" + getKey() + "=" + getValue() + "]"; 664 } else { 665 return "Iterator[]"; 666 } 667 } 668 } 669 670 679 public Set entrySet() { 680 if (delegateMap != null) { 681 return delegateMap.entrySet(); 682 } 683 return new EntrySet(this); 684 } 685 686 689 static class EntrySet extends AbstractSet { 690 private final Flat3Map parent; 691 692 EntrySet(Flat3Map parent) { 693 super(); 694 this.parent = parent; 695 } 696 697 public int size() { 698 return parent.size(); 699 } 700 701 public void clear() { 702 parent.clear(); 703 } 704 705 public boolean remove(Object obj) { 706 if (obj instanceof Map.Entry == false) { 707 return false; 708 } 709 Map.Entry entry = (Map.Entry ) obj; 710 Object key = entry.getKey(); 711 boolean result = parent.containsKey(key); 712 parent.remove(key); 713 return result; 714 } 715 716 public Iterator iterator() { 717 if (parent.delegateMap != null) { 718 return parent.delegateMap.entrySet().iterator(); 719 } 720 if (parent.size() == 0) { 721 return EmptyIterator.INSTANCE; 722 } 723 return new EntrySetIterator(parent); 724 } 725 } 726 727 730 static class EntrySetIterator implements Iterator , Map.Entry { 731 private final Flat3Map parent; 732 private int nextIndex = 0; 733 private boolean canRemove = false; 734 735 EntrySetIterator(Flat3Map parent) { 736 super(); 737 this.parent = parent; 738 } 739 740 public boolean hasNext() { 741 return (nextIndex < parent.size); 742 } 743 744 public Object next() { 745 if (hasNext() == false) { 746 throw new NoSuchElementException (AbstractHashedMap.NO_NEXT_ENTRY); 747 } 748 canRemove = true; 749 nextIndex++; 750 return this; 751 } 752 753 public void remove() { 754 if (canRemove == false) { 755 throw new IllegalStateException (AbstractHashedMap.REMOVE_INVALID); 756 } 757 parent.remove(getKey()); 758 nextIndex--; 759 canRemove = false; 760 } 761 762 public Object getKey() { 763 if (canRemove == false) { 764 throw new IllegalStateException (AbstractHashedMap.GETKEY_INVALID); 765 } 766 switch (nextIndex) { 767 case 3: 768 return parent.key3; 769 case 2: 770 return parent.key2; 771 case 1: 772 return parent.key1; 773 } 774 throw new IllegalStateException ("Invalid map index"); 775 } 776 777 public Object getValue() { 778 if (canRemove == false) { 779 throw new IllegalStateException (AbstractHashedMap.GETVALUE_INVALID); 780 } 781 switch (nextIndex) { 782 case 3: 783 return parent.value3; 784 case 2: 785 return parent.value2; 786 case 1: 787 return parent.value1; 788 } 789 throw new IllegalStateException ("Invalid map index"); 790 } 791 792 public Object setValue(Object value) { 793 if (canRemove == false) { 794 throw new IllegalStateException (AbstractHashedMap.SETVALUE_INVALID); 795 } 796 Object old = getValue(); 797 switch (nextIndex) { 798 case 3: 799 parent.value3 = value; 800 case 2: 801 parent.value2 = value; 802 case 1: 803 parent.value1 = value; 804 } 805 return old; 806 } 807 808 public boolean equals(Object obj) { 809 if (canRemove == false) { 810 return false; 811 } 812 if (obj instanceof Map.Entry == false) { 813 return false; 814 } 815 Map.Entry other = (Map.Entry ) obj; 816 Object key = getKey(); 817 Object value = getValue(); 818 return (key == null ? other.getKey() == null : key.equals(other.getKey())) && 819 (value == null ? other.getValue() == null : value.equals(other.getValue())); 820 } 821 822 public int hashCode() { 823 if (canRemove == false) { 824 return 0; 825 } 826 Object key = getKey(); 827 Object value = getValue(); 828 return (key == null ? 0 : key.hashCode()) ^ 829 (value == null ? 0 : value.hashCode()); 830 } 831 832 public String toString() { 833 if (canRemove) { 834 return getKey() + "=" + getValue(); 835 } else { 836 return ""; 837 } 838 } 839 } 840 841 848 public Set keySet() { 849 if (delegateMap != null) { 850 return delegateMap.keySet(); 851 } 852 return new KeySet(this); 853 } 854 855 858 static class KeySet extends AbstractSet { 859 private final Flat3Map parent; 860 861 KeySet(Flat3Map parent) { 862 super(); 863 this.parent = parent; 864 } 865 866 public int size() { 867 return parent.size(); 868 } 869 870 public void clear() { 871 parent.clear(); 872 } 873 874 public boolean contains(Object key) { 875 return parent.containsKey(key); 876 } 877 878 public boolean remove(Object key) { 879 boolean result = parent.containsKey(key); 880 parent.remove(key); 881 return result; 882 } 883 884 public Iterator iterator() { 885 if (parent.delegateMap != null) { 886 return parent.delegateMap.keySet().iterator(); 887 } 888 if (parent.size() == 0) { 889 return EmptyIterator.INSTANCE; 890 } 891 return new KeySetIterator(parent); 892 } 893 } 894 895 898 static class KeySetIterator extends EntrySetIterator { 899 900 KeySetIterator(Flat3Map parent) { 901 super(parent); 902 } 903 904 public Object next() { 905 super.next(); 906 return getKey(); 907 } 908 } 909 910 917 public Collection values() { 918 if (delegateMap != null) { 919 return delegateMap.values(); 920 } 921 return new Values(this); 922 } 923 924 927 static class Values extends AbstractCollection { 928 private final Flat3Map parent; 929 930 Values(Flat3Map parent) { 931 super(); 932 this.parent = parent; 933 } 934 935 public int size() { 936 return parent.size(); 937 } 938 939 public void clear() { 940 parent.clear(); 941 } 942 943 public boolean contains(Object value) { 944 return parent.containsValue(value); 945 } 946 947 public Iterator iterator() { 948 if (parent.delegateMap != null) { 949 return parent.delegateMap.values().iterator(); 950 } 951 if (parent.size() == 0) { 952 return EmptyIterator.INSTANCE; 953 } 954 return new ValuesIterator(parent); 955 } 956 } 957 958 961 static class ValuesIterator extends EntrySetIterator { 962 963 ValuesIterator(Flat3Map parent) { 964 super(parent); 965 } 966 967 public Object next() { 968 super.next(); 969 return getValue(); 970 } 971 } 972 973 977 private void writeObject(ObjectOutputStream out) throws IOException { 978 out.defaultWriteObject(); 979 out.writeInt(size()); 980 for (MapIterator it = mapIterator(); it.hasNext();) { 981 out.writeObject(it.next()); out.writeObject(it.getValue()); } 984 } 985 986 989 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 990 in.defaultReadObject(); 991 int count = in.readInt(); 992 if (count > 3) { 993 delegateMap = createDelegateMap(); 994 } 995 for (int i = count; i > 0; i--) { 996 put(in.readObject(), in.readObject()); 997 } 998 } 999 1000 1007 public Object clone() { 1008 try { 1009 Flat3Map cloned = (Flat3Map) super.clone(); 1010 if (cloned.delegateMap != null) { 1011 cloned.delegateMap = (HashedMap) cloned.delegateMap.clone(); 1012 } 1013 return cloned; 1014 } catch (CloneNotSupportedException ex) { 1015 throw new InternalError (); 1016 } 1017 } 1018 1019 1025 public boolean equals(Object obj) { 1026 if (obj == this) { 1027 return true; 1028 } 1029 if (delegateMap != null) { 1030 return delegateMap.equals(obj); 1031 } 1032 if (obj instanceof Map == false) { 1033 return false; 1034 } 1035 Map other = (Map ) obj; 1036 if (size != other.size()) { 1037 return false; 1038 } 1039 if (size > 0) { 1040 Object otherValue = null; 1041 switch (size) { case 3: 1043 if (other.containsKey(key3) == false) { 1044 otherValue = other.get(key3); 1045 if (value3 == null ? otherValue != null : !value3.equals(otherValue)) { 1046 return false; 1047 } 1048 } 1049 case 2: 1050 if (other.containsKey(key2) == false) { 1051 otherValue = other.get(key2); 1052 if (value2 == null ? otherValue != null : !value2.equals(otherValue)) { 1053 return false; 1054 } 1055 } 1056 case 1: 1057 if (other.containsKey(key1) == false) { 1058 otherValue = other.get(key1); 1059 if (value1 == null ? otherValue != null : !value1.equals(otherValue)) { 1060 return false; 1061 } 1062 } 1063 } 1064 } 1065 return true; 1066 } 1067 1068 1073 public int hashCode() { 1074 if (delegateMap != null) { 1075 return delegateMap.hashCode(); 1076 } 1077 int total = 0; 1078 switch (size) { case 3: 1080 total += (hash3 ^ (value3 == null ? 0 : value3.hashCode())); 1081 case 2: 1082 total += (hash2 ^ (value2 == null ? 0 : value2.hashCode())); 1083 case 1: 1084 total += (hash1 ^ (value1 == null ? 0 : value1.hashCode())); 1085 } 1086 return total; 1087 } 1088 1089 1094 public String toString() { 1095 if (delegateMap != null) { 1096 return delegateMap.toString(); 1097 } 1098 if (size == 0) { 1099 return "{}"; 1100 } 1101 StringBuffer buf = new StringBuffer (128); 1102 buf.append('{'); 1103 switch (size) { case 3: 1105 buf.append((key3 == this ? "(this Map)" : key3)); 1106 buf.append('='); 1107 buf.append((value3 == this ? "(this Map)" : value3)); 1108 buf.append(','); 1109 case 2: 1110 buf.append((key2 == this ? "(this Map)" : key2)); 1111 buf.append('='); 1112 buf.append((value2 == this ? "(this Map)" : value2)); 1113 buf.append(','); 1114 case 1: 1115 buf.append((key1 == this ? "(this Map)" : key1)); 1116 buf.append('='); 1117 buf.append((value1 == this ? "(this Map)" : value1)); 1118 } 1119 buf.append('}'); 1120 return buf.toString(); 1121 } 1122 1123} 1124 | Popular Tags |