1 16 package org.apache.commons.collections.map; 17 18 import java.io.Serializable ; 19 import java.util.Collection ; 20 import java.util.Iterator ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.apache.commons.collections.IterableMap; 25 import org.apache.commons.collections.MapIterator; 26 import org.apache.commons.collections.keyvalue.MultiKey; 27 28 74 public class MultiKeyMap 75 implements IterableMap, Serializable { 76 77 78 private static final long serialVersionUID = -1788199231038721040L; 79 80 81 protected final AbstractHashedMap map; 82 83 91 public static MultiKeyMap decorate(AbstractHashedMap map) { 92 if (map == null) { 93 throw new IllegalArgumentException ("Map must not be null"); 94 } 95 if (map.size() > 0) { 96 throw new IllegalArgumentException ("Map must be empty"); 97 } 98 return new MultiKeyMap(map); 99 } 100 101 105 public MultiKeyMap() { 106 super(); 107 map = new HashedMap(); 108 } 109 110 118 protected MultiKeyMap(AbstractHashedMap map) { 119 super(); 120 this.map = map; 121 } 122 123 131 public Object get(Object key1, Object key2) { 132 int hashCode = hash(key1, key2); 133 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 134 while (entry != null) { 135 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { 136 return entry.getValue(); 137 } 138 entry = entry.next; 139 } 140 return null; 141 } 142 143 150 public boolean containsKey(Object key1, Object key2) { 151 int hashCode = hash(key1, key2); 152 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 153 while (entry != null) { 154 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { 155 return true; 156 } 157 entry = entry.next; 158 } 159 return false; 160 } 161 162 170 public Object put(Object key1, Object key2, Object value) { 171 int hashCode = hash(key1, key2); 172 int index = map.hashIndex(hashCode, map.data.length); 173 AbstractHashedMap.HashEntry entry = map.data[index]; 174 while (entry != null) { 175 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { 176 Object oldValue = entry.getValue(); 177 map.updateEntry(entry, value); 178 return oldValue; 179 } 180 entry = entry.next; 181 } 182 183 map.addMapping(index, hashCode, new MultiKey(key1, key2), value); 184 return null; 185 } 186 187 194 public Object remove(Object key1, Object key2) { 195 int hashCode = hash(key1, key2); 196 int index = map.hashIndex(hashCode, map.data.length); 197 AbstractHashedMap.HashEntry entry = map.data[index]; 198 AbstractHashedMap.HashEntry previous = null; 199 while (entry != null) { 200 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { 201 Object oldValue = entry.getValue(); 202 map.removeMapping(entry, index, previous); 203 return oldValue; 204 } 205 previous = entry; 206 entry = entry.next; 207 } 208 return null; 209 } 210 211 218 protected int hash(Object key1, Object key2) { 219 int h = 0; 220 if (key1 != null) { 221 h ^= key1.hashCode(); 222 } 223 if (key2 != null) { 224 h ^= key2.hashCode(); 225 } 226 h += ~(h << 9); 227 h ^= (h >>> 14); 228 h += (h << 4); 229 h ^= (h >>> 10); 230 return h; 231 } 232 233 241 protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2) { 242 MultiKey multi = (MultiKey) entry.getKey(); 243 return 244 multi.size() == 2 && 245 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 246 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))); 247 } 248 249 258 public Object get(Object key1, Object key2, Object key3) { 259 int hashCode = hash(key1, key2, key3); 260 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 261 while (entry != null) { 262 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { 263 return entry.getValue(); 264 } 265 entry = entry.next; 266 } 267 return null; 268 } 269 270 278 public boolean containsKey(Object key1, Object key2, Object key3) { 279 int hashCode = hash(key1, key2, key3); 280 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 281 while (entry != null) { 282 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { 283 return true; 284 } 285 entry = entry.next; 286 } 287 return false; 288 } 289 290 299 public Object put(Object key1, Object key2, Object key3, Object value) { 300 int hashCode = hash(key1, key2, key3); 301 int index = map.hashIndex(hashCode, map.data.length); 302 AbstractHashedMap.HashEntry entry = map.data[index]; 303 while (entry != null) { 304 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { 305 Object oldValue = entry.getValue(); 306 map.updateEntry(entry, value); 307 return oldValue; 308 } 309 entry = entry.next; 310 } 311 312 map.addMapping(index, hashCode, new MultiKey(key1, key2, key3), value); 313 return null; 314 } 315 316 324 public Object remove(Object key1, Object key2, Object key3) { 325 int hashCode = hash(key1, key2, key3); 326 int index = map.hashIndex(hashCode, map.data.length); 327 AbstractHashedMap.HashEntry entry = map.data[index]; 328 AbstractHashedMap.HashEntry previous = null; 329 while (entry != null) { 330 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { 331 Object oldValue = entry.getValue(); 332 map.removeMapping(entry, index, previous); 333 return oldValue; 334 } 335 previous = entry; 336 entry = entry.next; 337 } 338 return null; 339 } 340 341 349 protected int hash(Object key1, Object key2, Object key3) { 350 int h = 0; 351 if (key1 != null) { 352 h ^= key1.hashCode(); 353 } 354 if (key2 != null) { 355 h ^= key2.hashCode(); 356 } 357 if (key3 != null) { 358 h ^= key3.hashCode(); 359 } 360 h += ~(h << 9); 361 h ^= (h >>> 14); 362 h += (h << 4); 363 h ^= (h >>> 10); 364 return h; 365 } 366 367 376 protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3) { 377 MultiKey multi = (MultiKey) entry.getKey(); 378 return 379 multi.size() == 3 && 380 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 381 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && 382 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))); 383 } 384 385 395 public Object get(Object key1, Object key2, Object key3, Object key4) { 396 int hashCode = hash(key1, key2, key3, key4); 397 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 398 while (entry != null) { 399 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { 400 return entry.getValue(); 401 } 402 entry = entry.next; 403 } 404 return null; 405 } 406 407 416 public boolean containsKey(Object key1, Object key2, Object key3, Object key4) { 417 int hashCode = hash(key1, key2, key3, key4); 418 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 419 while (entry != null) { 420 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { 421 return true; 422 } 423 entry = entry.next; 424 } 425 return false; 426 } 427 428 438 public Object put(Object key1, Object key2, Object key3, Object key4, Object value) { 439 int hashCode = hash(key1, key2, key3, key4); 440 int index = map.hashIndex(hashCode, map.data.length); 441 AbstractHashedMap.HashEntry entry = map.data[index]; 442 while (entry != null) { 443 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { 444 Object oldValue = entry.getValue(); 445 map.updateEntry(entry, value); 446 return oldValue; 447 } 448 entry = entry.next; 449 } 450 451 map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4), value); 452 return null; 453 } 454 455 464 public Object remove(Object key1, Object key2, Object key3, Object key4) { 465 int hashCode = hash(key1, key2, key3, key4); 466 int index = map.hashIndex(hashCode, map.data.length); 467 AbstractHashedMap.HashEntry entry = map.data[index]; 468 AbstractHashedMap.HashEntry previous = null; 469 while (entry != null) { 470 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { 471 Object oldValue = entry.getValue(); 472 map.removeMapping(entry, index, previous); 473 return oldValue; 474 } 475 previous = entry; 476 entry = entry.next; 477 } 478 return null; 479 } 480 481 490 protected int hash(Object key1, Object key2, Object key3, Object key4) { 491 int h = 0; 492 if (key1 != null) { 493 h ^= key1.hashCode(); 494 } 495 if (key2 != null) { 496 h ^= key2.hashCode(); 497 } 498 if (key3 != null) { 499 h ^= key3.hashCode(); 500 } 501 if (key4 != null) { 502 h ^= key4.hashCode(); 503 } 504 h += ~(h << 9); 505 h ^= (h >>> 14); 506 h += (h << 4); 507 h ^= (h >>> 10); 508 return h; 509 } 510 511 521 protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4) { 522 MultiKey multi = (MultiKey) entry.getKey(); 523 return 524 multi.size() == 4 && 525 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 526 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && 527 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && 528 (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))); 529 } 530 531 542 public Object get(Object key1, Object key2, Object key3, Object key4, Object key5) { 543 int hashCode = hash(key1, key2, key3, key4, key5); 544 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 545 while (entry != null) { 546 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { 547 return entry.getValue(); 548 } 549 entry = entry.next; 550 } 551 return null; 552 } 553 554 564 public boolean containsKey(Object key1, Object key2, Object key3, Object key4, Object key5) { 565 int hashCode = hash(key1, key2, key3, key4, key5); 566 AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; 567 while (entry != null) { 568 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { 569 return true; 570 } 571 entry = entry.next; 572 } 573 return false; 574 } 575 576 587 public Object put(Object key1, Object key2, Object key3, Object key4, Object key5, Object value) { 588 int hashCode = hash(key1, key2, key3, key4, key5); 589 int index = map.hashIndex(hashCode, map.data.length); 590 AbstractHashedMap.HashEntry entry = map.data[index]; 591 while (entry != null) { 592 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { 593 Object oldValue = entry.getValue(); 594 map.updateEntry(entry, value); 595 return oldValue; 596 } 597 entry = entry.next; 598 } 599 600 map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4, key5), value); 601 return null; 602 } 603 604 614 public Object remove(Object key1, Object key2, Object key3, Object key4, Object key5) { 615 int hashCode = hash(key1, key2, key3, key4, key5); 616 int index = map.hashIndex(hashCode, map.data.length); 617 AbstractHashedMap.HashEntry entry = map.data[index]; 618 AbstractHashedMap.HashEntry previous = null; 619 while (entry != null) { 620 if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { 621 Object oldValue = entry.getValue(); 622 map.removeMapping(entry, index, previous); 623 return oldValue; 624 } 625 previous = entry; 626 entry = entry.next; 627 } 628 return null; 629 } 630 631 641 protected int hash(Object key1, Object key2, Object key3, Object key4, Object key5) { 642 int h = 0; 643 if (key1 != null) { 644 h ^= key1.hashCode(); 645 } 646 if (key2 != null) { 647 h ^= key2.hashCode(); 648 } 649 if (key3 != null) { 650 h ^= key3.hashCode(); 651 } 652 if (key4 != null) { 653 h ^= key4.hashCode(); 654 } 655 if (key5 != null) { 656 h ^= key5.hashCode(); 657 } 658 h += ~(h << 9); 659 h ^= (h >>> 14); 660 h += (h << 4); 661 h ^= (h >>> 10); 662 return h; 663 } 664 665 676 protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4, Object key5) { 677 MultiKey multi = (MultiKey) entry.getKey(); 678 return 679 multi.size() == 5 && 680 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 681 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && 682 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && 683 (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))) && 684 (key5 == null ? multi.getKey(4) == null : key5.equals(multi.getKey(4))); 685 } 686 687 697 public boolean removeAll(Object key1) { 698 boolean modified = false; 699 MapIterator it = mapIterator(); 700 while (it.hasNext()) { 701 MultiKey multi = (MultiKey) it.next(); 702 if (multi.size() >= 1 && 703 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0)))) { 704 it.remove(); 705 modified = true; 706 } 707 } 708 return modified; 709 } 710 711 721 public boolean removeAll(Object key1, Object key2) { 722 boolean modified = false; 723 MapIterator it = mapIterator(); 724 while (it.hasNext()) { 725 MultiKey multi = (MultiKey) it.next(); 726 if (multi.size() >= 2 && 727 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 728 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)))) { 729 it.remove(); 730 modified = true; 731 } 732 } 733 return modified; 734 } 735 736 747 public boolean removeAll(Object key1, Object key2, Object key3) { 748 boolean modified = false; 749 MapIterator it = mapIterator(); 750 while (it.hasNext()) { 751 MultiKey multi = (MultiKey) it.next(); 752 if (multi.size() >= 3 && 753 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 754 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && 755 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2)))) { 756 it.remove(); 757 modified = true; 758 } 759 } 760 return modified; 761 } 762 763 775 public boolean removeAll(Object key1, Object key2, Object key3, Object key4) { 776 boolean modified = false; 777 MapIterator it = mapIterator(); 778 while (it.hasNext()) { 779 MultiKey multi = (MultiKey) it.next(); 780 if (multi.size() >= 4 && 781 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && 782 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && 783 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && 784 (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3)))) { 785 it.remove(); 786 modified = true; 787 } 788 } 789 return modified; 790 } 791 792 798 protected void checkKey(Object key) { 799 if (key == null) { 800 throw new NullPointerException ("Key must not be null"); 801 } 802 if (key instanceof MultiKey == false) { 803 throw new ClassCastException ("Key must be a MultiKey"); 804 } 805 } 806 807 812 public Object clone() { 813 return new MultiKeyMap((AbstractHashedMap) map.clone()); 814 } 815 816 826 public Object put(Object key, Object value) { 827 checkKey(key); 828 return map.put(key, value); 829 } 830 831 841 public void putAll(Map mapToCopy) { 842 for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) { 843 Object key = it.next(); 844 checkKey(key); 845 } 846 map.putAll(mapToCopy); 847 } 848 849 public MapIterator mapIterator() { 851 return map.mapIterator(); 852 } 853 854 public int size() { 855 return map.size(); 856 } 857 858 public boolean isEmpty() { 859 return map.isEmpty(); 860 } 861 862 public boolean containsKey(Object key) { 863 return map.containsKey(key); 864 } 865 866 public boolean containsValue(Object value) { 867 return map.containsValue(value); 868 } 869 870 public Object get(Object key) { 871 return map.get(key); 872 } 873 874 public Object remove(Object key) { 875 return map.remove(key); 876 } 877 878 public void clear() { 879 map.clear(); 880 } 881 882 public Set keySet() { 883 return map.keySet(); 884 } 885 886 public Collection values() { 887 return map.values(); 888 } 889 890 public Set entrySet() { 891 return map.entrySet(); 892 } 893 894 public boolean equals(Object obj) { 895 if (obj == this) { 896 return true; 897 } 898 return map.equals(obj); 899 } 900 901 public int hashCode() { 902 return map.hashCode(); 903 } 904 905 public String toString() { 906 return map.toString(); 907 } 908 909 } 910 | Popular Tags |