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.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          *   &amp;&amp;
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          *   &amp;&amp;
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 }