001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.collect; 016 017import static com.google.common.base.Preconditions.checkArgument; 018import static com.google.common.base.Preconditions.checkState; 019 020import com.google.common.annotations.GwtCompatible; 021import com.google.common.annotations.GwtIncompatible; 022import com.google.common.base.Objects; 023import com.google.common.primitives.Ints; 024 025import java.io.IOException; 026import java.io.ObjectInputStream; 027import java.io.ObjectOutputStream; 028import java.io.Serializable; 029import java.util.AbstractMap; 030import java.util.Arrays; 031import java.util.ConcurrentModificationException; 032import java.util.Iterator; 033import java.util.Map; 034import java.util.NoSuchElementException; 035import java.util.Set; 036 037import javax.annotation.Nullable; 038 039/** 040 * A {@link BiMap} backed by two hash tables. This implementation allows null keys and values. A 041 * {@code HashBiMap} and its inverse are both serializable. 042 * 043 * <p>See the Guava User Guide article on <a href= 044 * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap"> {@code BiMap} 045 * </a>. 046 * 047 * @author Louis Wasserman 048 * @author Mike Bostock 049 * @since 2.0 (imported from Google Collections Library) 050 */ 051@GwtCompatible(emulated = true) 052public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable { 053 054 /** 055 * Returns a new, empty {@code HashBiMap} with the default initial capacity (16). 056 */ 057 public static <K, V> HashBiMap<K, V> create() { 058 return create(16); 059 } 060 061 /** 062 * Constructs a new, empty bimap with the specified expected size. 063 * 064 * @param expectedSize the expected number of entries 065 * @throws IllegalArgumentException if the specified expected size is negative 066 */ 067 public static <K, V> HashBiMap<K, V> create(int expectedSize) { 068 return new HashBiMap<K, V>(expectedSize); 069 } 070 071 /** 072 * Constructs a new bimap containing initial values from {@code map}. The bimap is created with an 073 * initial capacity sufficient to hold the mappings in the specified map. 074 */ 075 public static <K, V> HashBiMap<K, V> create(Map<? extends K, ? extends V> map) { 076 HashBiMap<K, V> bimap = create(map.size()); 077 bimap.putAll(map); 078 return bimap; 079 } 080 081 private static final class BiEntry<K, V> { 082 final K key; 083 final int keyHash; 084 085 final V value; 086 final int valueHash; 087 088 @Nullable 089 BiEntry<K, V> nextInKToVBucket; 090 091 @Nullable 092 BiEntry<K, V> nextInVToKBucket; 093 094 BiEntry(K key, int keyHash, V value, int valueHash) { 095 this.key = key; 096 this.keyHash = keyHash; 097 this.value = value; 098 this.valueHash = valueHash; 099 } 100 } 101 102 private static final double LOAD_FACTOR = 1.0; 103 private static final int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO; 104 105 private transient BiEntry<K, V>[] hashTableKToV; 106 private transient BiEntry<K, V>[] hashTableVToK; 107 private transient int size; 108 private transient int mask; 109 private transient int modCount; 110 111 private HashBiMap(int expectedSize) { 112 init(expectedSize); 113 } 114 115 private void init(int expectedSize) { 116 checkArgument(expectedSize >= 0, "expectedSize must be >= 0 but was %s", expectedSize); 117 int tableSize = Integer.highestOneBit(Math.max(2, expectedSize) - 1) << 1; 118 if (tableSize < 0) { 119 tableSize = Ints.MAX_POWER_OF_TWO; 120 } 121 this.hashTableKToV = createTable(tableSize); 122 this.hashTableVToK = createTable(tableSize); 123 this.mask = tableSize - 1; 124 this.modCount = 0; 125 this.size = 0; 126 } 127 128 /** 129 * Finds and removes {@code entry} from the bucket linked lists in both the 130 * key-to-value direction and the value-to-key direction. 131 */ 132 private void delete(BiEntry<K, V> entry) { 133 int keyBucket = entry.keyHash & mask; 134 BiEntry<K, V> prevBucketEntry = null; 135 for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true; 136 bucketEntry = bucketEntry.nextInKToVBucket) { 137 if (bucketEntry == entry) { 138 if (prevBucketEntry == null) { 139 hashTableKToV[keyBucket] = entry.nextInKToVBucket; 140 } else { 141 prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket; 142 } 143 break; 144 } 145 prevBucketEntry = bucketEntry; 146 } 147 148 int valueBucket = entry.valueHash & mask; 149 prevBucketEntry = null; 150 for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];; 151 bucketEntry = bucketEntry.nextInVToKBucket) { 152 if (bucketEntry == entry) { 153 if (prevBucketEntry == null) { 154 hashTableVToK[valueBucket] = entry.nextInVToKBucket; 155 } else { 156 prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket; 157 } 158 break; 159 } 160 prevBucketEntry = bucketEntry; 161 } 162 163 size--; 164 modCount++; 165 } 166 167 private void insert(BiEntry<K, V> entry) { 168 int keyBucket = entry.keyHash & mask; 169 entry.nextInKToVBucket = hashTableKToV[keyBucket]; 170 hashTableKToV[keyBucket] = entry; 171 172 int valueBucket = entry.valueHash & mask; 173 entry.nextInVToKBucket = hashTableVToK[valueBucket]; 174 hashTableVToK[valueBucket] = entry; 175 176 size++; 177 modCount++; 178 } 179 180 private static int hash(@Nullable Object o) { 181 return Hashing.smear((o == null) ? 0 : o.hashCode()); 182 } 183 184 private BiEntry<K, V> seekByKey(@Nullable Object key, int keyHash) { 185 for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null; 186 entry = entry.nextInKToVBucket) { 187 if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) { 188 return entry; 189 } 190 } 191 return null; 192 } 193 194 private BiEntry<K, V> seekByValue(@Nullable Object value, int valueHash) { 195 for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null; 196 entry = entry.nextInVToKBucket) { 197 if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) { 198 return entry; 199 } 200 } 201 return null; 202 } 203 204 @Override 205 public boolean containsKey(@Nullable Object key) { 206 return seekByKey(key, hash(key)) != null; 207 } 208 209 @Override 210 public boolean containsValue(@Nullable Object value) { 211 return seekByValue(value, hash(value)) != null; 212 } 213 214 @Nullable 215 @Override 216 public V get(@Nullable Object key) { 217 BiEntry<K, V> entry = seekByKey(key, hash(key)); 218 return (entry == null) ? null : entry.value; 219 } 220 221 @Override 222 public V put(@Nullable K key, @Nullable V value) { 223 return put(key, value, false); 224 } 225 226 @Override 227 public V forcePut(@Nullable K key, @Nullable V value) { 228 return put(key, value, true); 229 } 230 231 private V put(@Nullable K key, @Nullable V value, boolean force) { 232 int keyHash = hash(key); 233 int valueHash = hash(value); 234 235 BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash); 236 if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash 237 && Objects.equal(value, oldEntryForKey.value)) { 238 return value; 239 } 240 241 BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash); 242 if (oldEntryForValue != null) { 243 if (force) { 244 delete(oldEntryForValue); 245 } else { 246 throw new IllegalArgumentException("value already present: " + value); 247 } 248 } 249 250 if (oldEntryForKey != null) { 251 delete(oldEntryForKey); 252 } 253 BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash); 254 insert(newEntry); 255 rehashIfNecessary(); 256 return (oldEntryForKey == null) ? null : oldEntryForKey.value; 257 } 258 259 @Nullable 260 private K putInverse(@Nullable V value, @Nullable K key, boolean force) { 261 int valueHash = hash(value); 262 int keyHash = hash(key); 263 264 BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash); 265 if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash 266 && Objects.equal(key, oldEntryForValue.key)) { 267 return key; 268 } 269 270 BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash); 271 if (oldEntryForKey != null) { 272 if (force) { 273 delete(oldEntryForKey); 274 } else { 275 throw new IllegalArgumentException("value already present: " + key); 276 } 277 } 278 279 if (oldEntryForValue != null) { 280 delete(oldEntryForValue); 281 } 282 BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash); 283 insert(newEntry); 284 rehashIfNecessary(); 285 return (oldEntryForValue == null) ? null : oldEntryForValue.key; 286 } 287 288 private void rehashIfNecessary() { 289 BiEntry<K, V>[] oldKToV = hashTableKToV; 290 if (size > LOAD_FACTOR * oldKToV.length && oldKToV.length < MAX_TABLE_SIZE) { 291 int newTableSize = oldKToV.length * 2; 292 293 this.hashTableKToV = createTable(newTableSize); 294 this.hashTableVToK = createTable(newTableSize); 295 this.mask = newTableSize - 1; 296 this.size = 0; 297 298 for (int bucket = 0; bucket < oldKToV.length; bucket++) { 299 BiEntry<K, V> entry = oldKToV[bucket]; 300 while (entry != null) { 301 BiEntry<K, V> nextEntry = entry.nextInKToVBucket; 302 insert(entry); 303 entry = nextEntry; 304 } 305 } 306 this.modCount++; 307 } 308 } 309 310 @SuppressWarnings("unchecked") 311 private BiEntry<K, V>[] createTable(int length) { 312 return new BiEntry[length]; 313 } 314 315 @Override 316 public V remove(@Nullable Object key) { 317 BiEntry<K, V> entry = seekByKey(key, hash(key)); 318 if (entry == null) { 319 return null; 320 } else { 321 delete(entry); 322 return entry.value; 323 } 324 } 325 326 @Override 327 public void clear() { 328 size = 0; 329 Arrays.fill(hashTableKToV, null); 330 Arrays.fill(hashTableVToK, null); 331 modCount++; 332 } 333 334 @Override 335 public int size() { 336 return size; 337 } 338 339 abstract class Itr<T> implements Iterator<T> { 340 int nextBucket = 0; 341 BiEntry<K, V> next = null; 342 BiEntry<K, V> toRemove = null; 343 int expectedModCount = modCount; 344 345 private void checkForConcurrentModification() { 346 if (modCount != expectedModCount) { 347 throw new ConcurrentModificationException(); 348 } 349 } 350 351 @Override 352 public boolean hasNext() { 353 checkForConcurrentModification(); 354 if (next != null) { 355 return true; 356 } 357 while (nextBucket < hashTableKToV.length) { 358 if (hashTableKToV[nextBucket] != null) { 359 next = hashTableKToV[nextBucket++]; 360 return true; 361 } 362 nextBucket++; 363 } 364 return false; 365 } 366 367 @Override 368 public T next() { 369 checkForConcurrentModification(); 370 if (!hasNext()) { 371 throw new NoSuchElementException(); 372 } 373 374 BiEntry<K, V> entry = next; 375 next = entry.nextInKToVBucket; 376 toRemove = entry; 377 return output(entry); 378 } 379 380 @Override 381 public void remove() { 382 checkForConcurrentModification(); 383 checkState(toRemove != null, "Only one remove() call allowed per call to next"); 384 delete(toRemove); 385 expectedModCount = modCount; 386 toRemove = null; 387 } 388 389 abstract T output(BiEntry<K, V> entry); 390 } 391 392 @Override 393 public Set<K> keySet() { 394 return new KeySet(); 395 } 396 397 private final class KeySet extends Maps.KeySet<K, V> { 398 @Override 399 Map<K, V> map() { 400 return HashBiMap.this; 401 } 402 403 @Override 404 public Iterator<K> iterator() { 405 return new Itr<K>() { 406 @Override 407 K output(BiEntry<K, V> entry) { 408 return entry.key; 409 } 410 }; 411 } 412 413 @Override 414 public boolean remove(@Nullable Object o) { 415 BiEntry<K, V> entry = seekByKey(o, hash(o)); 416 if (entry == null) { 417 return false; 418 } else { 419 delete(entry); 420 return true; 421 } 422 } 423 } 424 425 @Override 426 public Set<V> values() { 427 return inverse().keySet(); 428 } 429 430 @Override 431 public Set<Entry<K, V>> entrySet() { 432 return new EntrySet(); 433 } 434 435 private final class EntrySet extends Maps.EntrySet<K, V> { 436 @Override 437 Map<K, V> map() { 438 return HashBiMap.this; 439 } 440 441 @Override 442 public Iterator<Entry<K, V>> iterator() { 443 return new Itr<Entry<K, V>>() { 444 @Override 445 Entry<K, V> output(BiEntry<K, V> entry) { 446 return new MapEntry(entry); 447 } 448 449 class MapEntry extends AbstractMapEntry<K, V> { 450 BiEntry<K, V> delegate; 451 452 MapEntry(BiEntry<K, V> entry) { 453 this.delegate = entry; 454 } 455 456 @Override public K getKey() { 457 return delegate.key; 458 } 459 460 @Override public V getValue() { 461 return delegate.value; 462 } 463 464 @Override public V setValue(V value) { 465 V oldValue = delegate.value; 466 int valueHash = hash(value); 467 if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) { 468 return value; 469 } 470 checkArgument( 471 seekByValue(value, valueHash) == null, "value already present: %s", value); 472 delete(delegate); 473 BiEntry<K, V> newEntry = 474 new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash); 475 insert(newEntry); 476 expectedModCount = modCount; 477 if (toRemove == delegate) { 478 toRemove = newEntry; 479 } 480 delegate = newEntry; 481 return oldValue; 482 } 483 } 484 }; 485 } 486 } 487 488 private transient BiMap<V, K> inverse; 489 490 @Override 491 public BiMap<V, K> inverse() { 492 return (inverse == null) ? inverse = new Inverse() : inverse; 493 } 494 495 private final class Inverse extends AbstractMap<V, K> implements BiMap<V, K>, Serializable { 496 BiMap<K, V> forward() { 497 return HashBiMap.this; 498 } 499 500 @Override 501 public int size() { 502 return size; 503 } 504 505 @Override 506 public void clear() { 507 forward().clear(); 508 } 509 510 @Override 511 public boolean containsKey(@Nullable Object value) { 512 return forward().containsValue(value); 513 } 514 515 @Override 516 public K get(@Nullable Object value) { 517 BiEntry<K, V> entry = seekByValue(value, hash(value)); 518 return (entry == null) ? null : entry.key; 519 } 520 521 @Override 522 public K put(@Nullable V value, @Nullable K key) { 523 return putInverse(value, key, false); 524 } 525 526 @Override 527 public K forcePut(@Nullable V value, @Nullable K key) { 528 return putInverse(value, key, true); 529 } 530 531 @Override 532 public K remove(@Nullable Object value) { 533 BiEntry<K, V> entry = seekByValue(value, hash(value)); 534 if (entry == null) { 535 return null; 536 } else { 537 delete(entry); 538 return entry.key; 539 } 540 } 541 542 @Override 543 public BiMap<K, V> inverse() { 544 return forward(); 545 } 546 547 @Override 548 public Set<V> keySet() { 549 return new InverseKeySet(); 550 } 551 552 private final class InverseKeySet extends Maps.KeySet<V, K> { 553 @Override 554 Map<V, K> map() { 555 return Inverse.this; 556 } 557 558 @Override 559 public boolean remove(@Nullable Object o) { 560 BiEntry<K, V> entry = seekByValue(o, hash(o)); 561 if (entry == null) { 562 return false; 563 } else { 564 delete(entry); 565 return true; 566 } 567 } 568 569 @Override 570 public Iterator<V> iterator() { 571 return new Itr<V>() { 572 @Override V output(BiEntry<K, V> entry) { 573 return entry.value; 574 } 575 }; 576 } 577 } 578 579 @Override 580 public Set<K> values() { 581 return forward().keySet(); 582 } 583 584 @Override 585 public Set<Entry<V, K>> entrySet() { 586 return new Maps.EntrySet<V, K>() { 587 588 @Override 589 Map<V, K> map() { 590 return Inverse.this; 591 } 592 593 @Override 594 public Iterator<Entry<V, K>> iterator() { 595 return new Itr<Entry<V, K>>() { 596 @Override 597 Entry<V, K> output(BiEntry<K, V> entry) { 598 return new InverseEntry(entry); 599 } 600 601 class InverseEntry extends AbstractMapEntry<V, K> { 602 BiEntry<K, V> delegate; 603 604 InverseEntry(BiEntry<K, V> entry) { 605 this.delegate = entry; 606 } 607 608 @Override 609 public V getKey() { 610 return delegate.value; 611 } 612 613 @Override 614 public K getValue() { 615 return delegate.key; 616 } 617 618 @Override 619 public K setValue(K key) { 620 K oldKey = delegate.key; 621 int keyHash = hash(key); 622 if (keyHash == delegate.keyHash && Objects.equal(key, oldKey)) { 623 return key; 624 } 625 checkArgument(seekByKey(key, keyHash) == null, "value already present: %s", key); 626 delete(delegate); 627 BiEntry<K, V> newEntry = 628 new BiEntry<K, V>(key, keyHash, delegate.value, delegate.valueHash); 629 insert(newEntry); 630 expectedModCount = modCount; 631 // This is safe because entries can only get bumped up to earlier in the iteration, 632 // so they can't get revisited. 633 return oldKey; 634 } 635 } 636 }; 637 } 638 }; 639 } 640 641 Object writeReplace() { 642 return new InverseSerializedForm<K, V>(HashBiMap.this); 643 } 644 } 645 646 private static final class InverseSerializedForm<K, V> implements Serializable { 647 private final HashBiMap<K, V> bimap; 648 649 InverseSerializedForm(HashBiMap<K, V> bimap) { 650 this.bimap = bimap; 651 } 652 653 Object readResolve() { 654 return bimap.inverse(); 655 } 656 } 657 658 /** 659 * @serialData the number of entries, first key, first value, second key, second value, and so on. 660 */ 661 @GwtIncompatible("java.io.ObjectOutputStream") 662 private void writeObject(ObjectOutputStream stream) throws IOException { 663 stream.defaultWriteObject(); 664 Serialization.writeMap(this, stream); 665 } 666 667 @GwtIncompatible("java.io.ObjectInputStream") 668 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 669 stream.defaultReadObject(); 670 int size = Serialization.readCount(stream); 671 init(size); 672 Serialization.populateMap(this, stream, size); 673 } 674 675 @GwtIncompatible("Not needed in emulated source") 676 private static final long serialVersionUID = 0; 677}