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 }