1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package org.openjdk.bench.valhalla.sandbox.corelibs.corelibs.mapprotos; 27 28 import java.util.AbstractCollection; 29 import java.util.AbstractSet; 30 import java.util.Collection; 31 import java.util.Iterator; 32 import java.util.Map; 33 import java.util.Set; 34 35 /** 36 * This class provides a skeletal implementation of the {@code Map} 37 * interface, to minimize the effort required to implement this interface. 38 * 39 * <p>To implement an unmodifiable map, the programmer needs only to extend this 40 * class and provide an implementation for the {@code entrySet} method, which 41 * returns a set-view of the map's mappings. Typically, the returned set 42 * will, in turn, be implemented atop {@code AbstractSet}. This set should 43 * not support the {@code add} or {@code remove} methods, and its iterator 44 * should not support the {@code remove} method. 45 * 46 * <p>To implement a modifiable map, the programmer must additionally override 47 * this class's {@code put} method (which otherwise throws an 48 * {@code UnsupportedOperationException}), and the iterator returned by 49 * {@code entrySet().iterator()} must additionally implement its 50 * {@code remove} method. 51 * 52 * <p>The programmer should generally provide a void (no argument) and map 53 * constructor, as per the recommendation in the {@code Map} interface 54 * specification. 55 * 56 * <p>The documentation for each non-abstract method in this class describes its 57 * implementation in detail. Each of these methods may be overridden if the 58 * map being implemented admits a more efficient implementation. 59 * 60 * <p>This class is a member of the 61 * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework"> 62 * Java Collections Framework</a>. 63 * 64 * @param <K> the type of keys maintained by this map 65 * @param <V> the type of mapped values 66 * 67 * @author Josh Bloch 68 * @author Neal Gafter 69 * @see Map 70 * @see Collection 71 * @since 1.2 72 */ 73 74 public abstract class XAbstractMap<K,V> implements Map<K,V> { 75 /** 76 * Sole constructor. (For invocation by subclass constructors, typically 77 * implicit.) 78 */ 79 protected XAbstractMap() { 80 } 81 82 // Query Operations 83 84 /** 85 * {@inheritDoc} 86 * 87 * @implSpec 88 * This implementation returns {@code entrySet().size()}. 89 */ 90 public int size() { 91 return entrySet().size(); 92 } 93 94 /** 95 * {@inheritDoc} 96 * 97 * @implSpec 98 * This implementation returns {@code size() == 0}. 99 */ 100 public boolean isEmpty() { 101 return size() == 0; 102 } 103 104 /** 105 * {@inheritDoc} 106 * 107 * @implSpec 108 * This implementation iterates over {@code entrySet()} searching 109 * for an entry with the specified value. If such an entry is found, 110 * {@code true} is returned. If the iteration terminates without 111 * finding such an entry, {@code false} is returned. Note that this 112 * implementation requires linear time in the size of the map. 113 * 114 * @throws ClassCastException {@inheritDoc} 115 * @throws NullPointerException {@inheritDoc} 116 */ 117 public boolean containsValue(Object value) { 118 Iterator<Entry<K,V>> i = entrySet().iterator(); 119 if (value==null) { 120 while (i.hasNext()) { 121 Entry<K,V> e = i.next(); 122 if (e.getValue()==null) 123 return true; 124 } 125 } else { 126 while (i.hasNext()) { 127 Entry<K,V> e = i.next(); 128 if (value.equals(e.getValue())) 129 return true; 130 } 131 } 132 return false; 133 } 134 135 /** 136 * {@inheritDoc} 137 * 138 * @implSpec 139 * This implementation iterates over {@code entrySet()} searching 140 * for an entry with the specified key. If such an entry is found, 141 * {@code true} is returned. If the iteration terminates without 142 * finding such an entry, {@code false} is returned. Note that this 143 * implementation requires linear time in the size of the map; many 144 * implementations will override this method. 145 * 146 * @throws ClassCastException {@inheritDoc} 147 * @throws NullPointerException {@inheritDoc} 148 */ 149 public boolean containsKey(Object key) { 150 Iterator<Map.Entry<K,V>> i = entrySet().iterator(); 151 if (key==null) { 152 while (i.hasNext()) { 153 Entry<K,V> e = i.next(); 154 if (e.getKey()==null) 155 return true; 156 } 157 } else { 158 while (i.hasNext()) { 159 Entry<K,V> e = i.next(); 160 if (key.equals(e.getKey())) 161 return true; 162 } 163 } 164 return false; 165 } 166 167 /** 168 * {@inheritDoc} 169 * 170 * @implSpec 171 * This implementation iterates over {@code entrySet()} searching 172 * for an entry with the specified key. If such an entry is found, 173 * the entry's value is returned. If the iteration terminates without 174 * finding such an entry, {@code null} is returned. Note that this 175 * implementation requires linear time in the size of the map; many 176 * implementations will override this method. 177 * 178 * @throws ClassCastException {@inheritDoc} 179 * @throws NullPointerException {@inheritDoc} 180 */ 181 public V get(Object key) { 182 Iterator<Entry<K,V>> i = entrySet().iterator(); 183 if (key==null) { 184 while (i.hasNext()) { 185 Entry<K,V> e = i.next(); 186 if (e.getKey()==null) 187 return e.getValue(); 188 } 189 } else { 190 while (i.hasNext()) { 191 Entry<K,V> e = i.next(); 192 if (key.equals(e.getKey())) 193 return e.getValue(); 194 } 195 } 196 return null; 197 } 198 199 200 // Modification Operations 201 202 /** 203 * {@inheritDoc} 204 * 205 * @implSpec 206 * This implementation always throws an 207 * {@code UnsupportedOperationException}. 208 * 209 * @throws UnsupportedOperationException {@inheritDoc} 210 * @throws ClassCastException {@inheritDoc} 211 * @throws NullPointerException {@inheritDoc} 212 * @throws IllegalArgumentException {@inheritDoc} 213 */ 214 public V put(K key, V value) { 215 throw new UnsupportedOperationException(); 216 } 217 218 /** 219 * {@inheritDoc} 220 * 221 * @implSpec 222 * This implementation iterates over {@code entrySet()} searching for an 223 * entry with the specified key. If such an entry is found, its value is 224 * obtained with its {@code getValue} operation, the entry is removed 225 * from the collection (and the backing map) with the iterator's 226 * {@code remove} operation, and the saved value is returned. If the 227 * iteration terminates without finding such an entry, {@code null} is 228 * returned. Note that this implementation requires linear time in the 229 * size of the map; many implementations will override this method. 230 * 231 * <p>Note that this implementation throws an 232 * {@code UnsupportedOperationException} if the {@code entrySet} 233 * iterator does not support the {@code remove} method and this map 234 * contains a mapping for the specified key. 235 * 236 * @throws UnsupportedOperationException {@inheritDoc} 237 * @throws ClassCastException {@inheritDoc} 238 * @throws NullPointerException {@inheritDoc} 239 */ 240 public V remove(Object key) { 241 Iterator<Entry<K,V>> i = entrySet().iterator(); 242 Entry<K,V> correctEntry = null; 243 if (key==null) { 244 while (correctEntry==null && i.hasNext()) { 245 Entry<K,V> e = i.next(); 246 if (e.getKey()==null) 247 correctEntry = e; 248 } 249 } else { 250 while (correctEntry==null && i.hasNext()) { 251 Entry<K,V> e = i.next(); 252 if (key.equals(e.getKey())) 253 correctEntry = e; 254 } 255 } 256 257 V oldValue = null; 258 if (correctEntry !=null) { 259 oldValue = correctEntry.getValue(); 260 i.remove(); 261 } 262 return oldValue; 263 } 264 265 266 // Bulk Operations 267 268 /** 269 * {@inheritDoc} 270 * 271 * @implSpec 272 * This implementation iterates over the specified map's 273 * {@code entrySet()} collection, and calls this map's {@code put} 274 * operation once for each entry returned by the iteration. 275 * 276 * <p>Note that this implementation throws an 277 * {@code UnsupportedOperationException} if this map does not support 278 * the {@code put} operation and the specified map is nonempty. 279 * 280 * @throws UnsupportedOperationException {@inheritDoc} 281 * @throws ClassCastException {@inheritDoc} 282 * @throws NullPointerException {@inheritDoc} 283 * @throws IllegalArgumentException {@inheritDoc} 284 */ 285 public void putAll(Map<? extends K, ? extends V> m) { 286 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) 287 put(e.getKey(), e.getValue()); 288 } 289 290 /** 291 * {@inheritDoc} 292 * 293 * @implSpec 294 * This implementation calls {@code entrySet().clear()}. 295 * 296 * <p>Note that this implementation throws an 297 * {@code UnsupportedOperationException} if the {@code entrySet} 298 * does not support the {@code clear} operation. 299 * 300 * @throws UnsupportedOperationException {@inheritDoc} 301 */ 302 public void clear() { 303 entrySet().clear(); 304 } 305 306 307 // Views 308 309 /** 310 * Each of these fields are initialized to contain an instance of the 311 * appropriate view the first time this view is requested. The views are 312 * stateless, so there's no reason to create more than one of each. 313 * 314 * <p>Since there is no synchronization performed while accessing these fields, 315 * it is expected that java.util.Map view classes using these fields have 316 * no non-final fields (or any fields at all except for outer-this). Adhering 317 * to this rule would make the races on these fields benign. 318 * 319 * <p>It is also imperative that implementations read the field only once, 320 * as in: 321 * 322 * <pre> {@code 323 * public Set<K> keySet() { 324 * Set<K> ks = keySet; // single racy read 325 * if (ks == null) { 326 * ks = new KeySet(); 327 * keySet = ks; 328 * } 329 * return ks; 330 * } 331 *}</pre> 332 */ 333 transient Set<K> keySet; 334 transient Collection<V> values; 335 336 /** 337 * {@inheritDoc} 338 * 339 * @implSpec 340 * This implementation returns a set that subclasses {@link AbstractSet}. 341 * The subclass's iterator method returns a "wrapper object" over this 342 * map's {@code entrySet()} iterator. The {@code size} method 343 * delegates to this map's {@code size} method and the 344 * {@code contains} method delegates to this map's 345 * {@code containsKey} method. 346 * 347 * <p>The set is created the first time this method is called, 348 * and returned in response to all subsequent calls. No synchronization 349 * is performed, so there is a slight chance that multiple calls to this 350 * method will not all return the same set. 351 */ 352 public Set<K> keySet() { 353 Set<K> ks = keySet; 354 if (ks == null) { 355 ks = new AbstractSet<K>() { 356 public Iterator<K> iterator() { 357 return new Iterator<K>() { 358 private Iterator<Entry<K,V>> i = entrySet().iterator(); 359 360 public boolean hasNext() { 361 return i.hasNext(); 362 } 363 364 public K next() { 365 return i.next().getKey(); 366 } 367 368 public void remove() { 369 i.remove(); 370 } 371 }; 372 } 373 374 public int size() { 375 return XAbstractMap.this.size(); 376 } 377 378 public boolean isEmpty() { 379 return XAbstractMap.this.isEmpty(); 380 } 381 382 public void clear() { 383 XAbstractMap.this.clear(); 384 } 385 386 public boolean contains(Object k) { 387 return XAbstractMap.this.containsKey(k); 388 } 389 }; 390 keySet = ks; 391 } 392 return ks; 393 } 394 395 /** 396 * {@inheritDoc} 397 * 398 * @implSpec 399 * This implementation returns a collection that subclasses {@link 400 * AbstractCollection}. The subclass's iterator method returns a 401 * "wrapper object" over this map's {@code entrySet()} iterator. 402 * The {@code size} method delegates to this map's {@code size} 403 * method and the {@code contains} method delegates to this map's 404 * {@code containsValue} method. 405 * 406 * <p>The collection is created the first time this method is called, and 407 * returned in response to all subsequent calls. No synchronization is 408 * performed, so there is a slight chance that multiple calls to this 409 * method will not all return the same collection. 410 */ 411 public Collection<V> values() { 412 Collection<V> vals = values; 413 if (vals == null) { 414 vals = new AbstractCollection<V>() { 415 public Iterator<V> iterator() { 416 return new Iterator<V>() { 417 private Iterator<Entry<K,V>> i = entrySet().iterator(); 418 419 public boolean hasNext() { 420 return i.hasNext(); 421 } 422 423 public V next() { 424 return i.next().getValue(); 425 } 426 427 public void remove() { 428 i.remove(); 429 } 430 }; 431 } 432 433 public int size() { 434 return XAbstractMap.this.size(); 435 } 436 437 public boolean isEmpty() { 438 return XAbstractMap.this.isEmpty(); 439 } 440 441 public void clear() { 442 XAbstractMap.this.clear(); 443 } 444 445 public boolean contains(Object v) { 446 return XAbstractMap.this.containsValue(v); 447 } 448 }; 449 values = vals; 450 } 451 return vals; 452 } 453 454 public abstract Set<Entry<K,V>> entrySet(); 455 456 457 // Comparison and hashing 458 459 /** 460 * Compares the specified object with this map for equality. Returns 461 * {@code true} if the given object is also a map and the two maps 462 * represent the same mappings. More formally, two maps {@code m1} and 463 * {@code m2} represent the same mappings if 464 * {@code m1.entrySet().equals(m2.entrySet())}. This ensures that the 465 * {@code equals} method works properly across different implementations 466 * of the {@code Map} interface. 467 * 468 * @implSpec 469 * This implementation first checks if the specified object is this map; 470 * if so it returns {@code true}. Then, it checks if the specified 471 * object is a map whose size is identical to the size of this map; if 472 * not, it returns {@code false}. If so, it iterates over this map's 473 * {@code entrySet} collection, and checks that the specified map 474 * contains each mapping that this map contains. If the specified map 475 * fails to contain such a mapping, {@code false} is returned. If the 476 * iteration completes, {@code true} is returned. 477 * 478 * @param o object to be compared for equality with this map 479 * @return {@code true} if the specified object is equal to this map 480 */ 481 public boolean equals(Object o) { 482 if (o == this) 483 return true; 484 485 if (!(o instanceof Map)) 486 return false; 487 Map<?,?> m = (Map<?,?>) o; 488 if (m.size() != size()) 489 return false; 490 491 try { 492 for (Entry<K, V> e : entrySet()) { 493 K key = e.getKey(); 494 V value = e.getValue(); 495 if (value == null) { 496 if (!(m.get(key) == null && m.containsKey(key))) 497 return false; 498 } else { 499 if (!value.equals(m.get(key))) 500 return false; 501 } 502 } 503 } catch (ClassCastException unused) { 504 return false; 505 } catch (NullPointerException unused) { 506 return false; 507 } 508 509 return true; 510 } 511 512 /** 513 * Returns the hash code value for this map. The hash code of a map is 514 * defined to be the sum of the hash codes of each entry in the map's 515 * {@code entrySet()} view. This ensures that {@code m1.equals(m2)} 516 * implies that {@code m1.hashCode()==m2.hashCode()} for any two maps 517 * {@code m1} and {@code m2}, as required by the general contract of 518 * {@link Object#hashCode}. 519 * 520 * @implSpec 521 * This implementation iterates over {@code entrySet()}, calling 522 * {@link Map.Entry#hashCode hashCode()} on each element (entry) in the 523 * set, and adding up the results. 524 * 525 * @return the hash code value for this map 526 * @see Map.Entry#hashCode() 527 * @see Object#equals(Object) 528 * @see Set#equals(Object) 529 */ 530 public int hashCode() { 531 int h = 0; 532 for (Entry<K, V> entry : entrySet()) 533 h += entry.hashCode(); 534 return h; 535 } 536 537 /** 538 * Returns a string representation of this map. The string representation 539 * consists of a list of key-value mappings in the order returned by the 540 * map's {@code entrySet} view's iterator, enclosed in braces 541 * ({@code "{}"}). Adjacent mappings are separated by the characters 542 * {@code ", "} (comma and space). Each key-value mapping is rendered as 543 * the key followed by an equals sign ({@code "="}) followed by the 544 * associated value. Keys and values are converted to strings as by 545 * {@link String#valueOf(Object)}. 546 * 547 * @return a string representation of this map 548 */ 549 public String toString() { 550 Iterator<Entry<K,V>> i = entrySet().iterator(); 551 if (! i.hasNext()) 552 return "{}"; 553 554 StringBuilder sb = new StringBuilder(); 555 sb.append('{'); 556 for (;;) { 557 Entry<K,V> e = i.next(); 558 K key = e.getKey(); 559 V value = e.getValue(); 560 sb.append(key == this ? "(this Map)" : key); 561 sb.append('='); 562 sb.append(value == this ? "(this Map)" : value); 563 if (! i.hasNext()) 564 return sb.append('}').toString(); 565 sb.append(',').append(' '); 566 } 567 } 568 569 /** 570 * Returns a shallow copy of this {@code AbstractMap} instance: the keys 571 * and values themselves are not cloned. 572 * 573 * @return a shallow copy of this map 574 */ 575 protected Object clone() throws CloneNotSupportedException { 576 XAbstractMap<?,?> result = (XAbstractMap<?,?>)super.clone(); 577 result.keySet = null; 578 result.values = null; 579 return result; 580 } 581 582 /** 583 * Utility method for SimpleEntry and SimpleImmutableEntry. 584 * Test for equality, checking for nulls. 585 * 586 * NB: Do not replace with Object.equals until JDK-8015417 is resolved. 587 */ 588 private static boolean eq(Object o1, Object o2) { 589 return o1 == null ? o2 == null : o1.equals(o2); 590 } 591 592 // Implementation Note: SimpleEntry and SimpleImmutableEntry 593 // are distinct unrelated classes, even though they share 594 // some code. Since you can't add or subtract final-ness 595 // of a field in a subclass, they can't share representations, 596 // and the amount of duplicated code is too small to warrant 597 // exposing a common abstract class. 598 599 600 /** 601 * An Entry maintaining a key and a value. The value may be 602 * changed using the {@code setValue} method. This class 603 * facilitates the process of building custom map 604 * implementations. For example, it may be convenient to return 605 * arrays of {@code SimpleEntry} instances in method 606 * {@code Map.entrySet().toArray}. 607 * 608 * @since 1.6 609 */ 610 public static class SimpleEntry<K,V> 611 implements Entry<K,V>, java.io.Serializable 612 { 613 private static final long serialVersionUID = -8499721149061103585L; 614 615 private final K key; 616 private V value; 617 618 /** 619 * Creates an entry representing a mapping from the specified 620 * key to the specified value. 621 * 622 * @param key the key represented by this entry 623 * @param value the value represented by this entry 624 */ 625 public SimpleEntry(K key, V value) { 626 this.key = key; 627 this.value = value; 628 } 629 630 /** 631 * Creates an entry representing the same mapping as the 632 * specified entry. 633 * 634 * @param entry the entry to copy 635 */ 636 public SimpleEntry(Entry<? extends K, ? extends V> entry) { 637 this.key = entry.getKey(); 638 this.value = entry.getValue(); 639 } 640 641 /** 642 * Returns the key corresponding to this entry. 643 * 644 * @return the key corresponding to this entry 645 */ 646 public K getKey() { 647 return key; 648 } 649 650 /** 651 * Returns the value corresponding to this entry. 652 * 653 * @return the value corresponding to this entry 654 */ 655 public V getValue() { 656 return value; 657 } 658 659 /** 660 * Replaces the value corresponding to this entry with the specified 661 * value. 662 * 663 * @param value new value to be stored in this entry 664 * @return the old value corresponding to the entry 665 */ 666 public V setValue(V value) { 667 V oldValue = this.value; 668 this.value = value; 669 return oldValue; 670 } 671 672 /** 673 * Compares the specified object with this entry for equality. 674 * Returns {@code true} if the given object is also a map entry and 675 * the two entries represent the same mapping. More formally, two 676 * entries {@code e1} and {@code e2} represent the same mapping 677 * if<pre> 678 * (e1.getKey()==null ? 679 * e2.getKey()==null : 680 * e1.getKey().equals(e2.getKey())) 681 * && 682 * (e1.getValue()==null ? 683 * e2.getValue()==null : 684 * e1.getValue().equals(e2.getValue()))</pre> 685 * This ensures that the {@code equals} method works properly across 686 * different implementations of the {@code Map.Entry} interface. 687 * 688 * @param o object to be compared for equality with this map entry 689 * @return {@code true} if the specified object is equal to this map 690 * entry 691 * @see #hashCode 692 */ 693 public boolean equals(Object o) { 694 if (!(o instanceof Map.Entry)) 695 return false; 696 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 697 return eq(key, e.getKey()) && eq(value, e.getValue()); 698 } 699 700 /** 701 * Returns the hash code value for this map entry. The hash code 702 * of a map entry {@code e} is defined to be: <pre> 703 * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ 704 * (e.getValue()==null ? 0 : e.getValue().hashCode())</pre> 705 * This ensures that {@code e1.equals(e2)} implies that 706 * {@code e1.hashCode()==e2.hashCode()} for any two Entries 707 * {@code e1} and {@code e2}, as required by the general 708 * contract of {@link Object#hashCode}. 709 * 710 * @return the hash code value for this map entry 711 * @see #equals 712 */ 713 public int hashCode() { 714 return (key == null ? 0 : key.hashCode()) ^ 715 (value == null ? 0 : value.hashCode()); 716 } 717 718 /** 719 * Returns a String representation of this map entry. This 720 * implementation returns the string representation of this 721 * entry's key followed by the equals character ("{@code =}") 722 * followed by the string representation of this entry's value. 723 * 724 * @return a String representation of this map entry 725 */ 726 public String toString() { 727 return key + "=" + value; 728 } 729 730 } 731 732 /** 733 * An Entry maintaining an immutable key and value. This class 734 * does not support method {@code setValue}. This class may be 735 * convenient in methods that return thread-safe snapshots of 736 * key-value mappings. 737 * 738 * @since 1.6 739 */ 740 public static class SimpleImmutableEntry<K,V> 741 implements Entry<K,V>, java.io.Serializable 742 { 743 private static final long serialVersionUID = 7138329143949025153L; 744 745 private final K key; 746 private final V value; 747 748 /** 749 * Creates an entry representing a mapping from the specified 750 * key to the specified value. 751 * 752 * @param key the key represented by this entry 753 * @param value the value represented by this entry 754 */ 755 public SimpleImmutableEntry(K key, V value) { 756 this.key = key; 757 this.value = value; 758 } 759 760 /** 761 * Creates an entry representing the same mapping as the 762 * specified entry. 763 * 764 * @param entry the entry to copy 765 */ 766 public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) { 767 this.key = entry.getKey(); 768 this.value = entry.getValue(); 769 } 770 771 /** 772 * Returns the key corresponding to this entry. 773 * 774 * @return the key corresponding to this entry 775 */ 776 public K getKey() { 777 return key; 778 } 779 780 /** 781 * Returns the value corresponding to this entry. 782 * 783 * @return the value corresponding to this entry 784 */ 785 public V getValue() { 786 return value; 787 } 788 789 /** 790 * Replaces the value corresponding to this entry with the specified 791 * value (optional operation). This implementation simply throws 792 * {@code UnsupportedOperationException}, as this class implements 793 * an <i>immutable</i> map entry. 794 * 795 * @param value new value to be stored in this entry 796 * @return (Does not return) 797 * @throws UnsupportedOperationException always 798 */ 799 public V setValue(V value) { 800 throw new UnsupportedOperationException(); 801 } 802 803 /** 804 * Compares the specified object with this entry for equality. 805 * Returns {@code true} if the given object is also a map entry and 806 * the two entries represent the same mapping. More formally, two 807 * entries {@code e1} and {@code e2} represent the same mapping 808 * if<pre> 809 * (e1.getKey()==null ? 810 * e2.getKey()==null : 811 * e1.getKey().equals(e2.getKey())) 812 * && 813 * (e1.getValue()==null ? 814 * e2.getValue()==null : 815 * e1.getValue().equals(e2.getValue()))</pre> 816 * This ensures that the {@code equals} method works properly across 817 * different implementations of the {@code Map.Entry} interface. 818 * 819 * @param o object to be compared for equality with this map entry 820 * @return {@code true} if the specified object is equal to this map 821 * entry 822 * @see #hashCode 823 */ 824 public boolean equals(Object o) { 825 if (!(o instanceof Map.Entry)) 826 return false; 827 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 828 return eq(key, e.getKey()) && eq(value, e.getValue()); 829 } 830 831 /** 832 * Returns the hash code value for this map entry. The hash code 833 * of a map entry {@code e} is defined to be: <pre> 834 * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ 835 * (e.getValue()==null ? 0 : e.getValue().hashCode())</pre> 836 * This ensures that {@code e1.equals(e2)} implies that 837 * {@code e1.hashCode()==e2.hashCode()} for any two Entries 838 * {@code e1} and {@code e2}, as required by the general 839 * contract of {@link Object#hashCode}. 840 * 841 * @return the hash code value for this map entry 842 * @see #equals 843 */ 844 public int hashCode() { 845 return (key == null ? 0 : key.hashCode()) ^ 846 (value == null ? 0 : value.hashCode()); 847 } 848 849 /** 850 * Returns a String representation of this map entry. This 851 * implementation returns the string representation of this 852 * entry's key followed by the equals character ("{@code =}") 853 * followed by the string representation of this entry's value. 854 * 855 * @return a String representation of this map entry 856 */ 857 public String toString() { 858 return key + "=" + value; 859 } 860 861 } 862 863 }