--- jsr166/src/main/java/util/AbstractMap.java 2005/06/20 18:02:22 1.13 +++ jsr166/src/main/java/util/AbstractMap.java 2007/05/20 07:54:01 1.24 @@ -1,12 +1,29 @@ /* - * %W% %E% + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. */ package java.util; -import java.util.*; // for javadoc (till 6280605 is fixed) import java.util.Map.Entry; /** @@ -30,12 +47,12 @@ import java.util.Map.Entry; * constructor, as per the recommendation in the Map interface * specification. * - *

The documentation for each non-abstract methods in this class describes its + *

The documentation for each non-abstract method in this class describes its * implementation in detail. Each of these methods may be overridden if the * map being implemented admits a more efficient implementation. * *

This class is a member of the - * + * * Java Collections Framework. * * @param the type of keys maintained by this map @@ -253,11 +270,8 @@ public abstract class AbstractMap i * @throws IllegalArgumentException {@inheritDoc} */ public void putAll(Map m) { - Iterator> i = m.entrySet().iterator(); - while (i.hasNext()) { - Entry e = i.next(); - put(e.getKey(), e.getValue()); - } + for (Map.Entry e : m.entrySet()) + put(e.getKey(), e.getValue()); } /** @@ -388,7 +402,13 @@ public abstract class AbstractMap i // Comparison and hashing /** - * {@inheritDoc} + * Compares the specified object with this map for equality. Returns + * true if the given object is also a map and the two maps + * represent the same mappings. More formally, two maps m1 and + * m2 represent the same mappings if + * m1.entrySet().equals(m2.entrySet()). This ensures that the + * equals method works properly across different implementations + * of the Map interface. * *

This implementation first checks if the specified object is this map; * if so it returns true. Then, it checks if the specified @@ -398,6 +418,9 @@ public abstract class AbstractMap i * contains each mapping that this map contains. If the specified map * fails to contain such a mapping, false is returned. If the * iteration completes, true is returned. + * + * @param o object to be compared for equality with this map + * @return true if the specified object is equal to this map */ public boolean equals(Object o) { if (o == this) @@ -433,14 +456,19 @@ public abstract class AbstractMap i } /** - * {@inheritDoc} + * Returns the hash code value for this map. The hash code of a map is + * defined to be the sum of the hash codes of each entry in the map's + * entrySet() view. This ensures that m1.equals(m2) + * implies that m1.hashCode()==m2.hashCode() for any two maps + * m1 and m2, as required by the general contract of + * {@link Object#hashCode}. * *

This implementation iterates over entrySet(), calling - * hashCode() on each element (entry) in the set, and - * adding up the results. + * {@link Map.Entry#hashCode hashCode()} on each element (entry) in the + * set, and adding up the results. * + * @return the hash code value for this map * @see Map.Entry#hashCode() - * @see Object#hashCode() * @see Object#equals(Object) * @see Set#equals(Object) */ @@ -460,43 +488,28 @@ public abstract class AbstractMap i * ", " (comma and space). Each key-value mapping is rendered as * the key followed by an equals sign ("=") followed by the * associated value. Keys and values are converted to strings as by - * String.valueOf(Object).

+ * {@link String#valueOf(Object)}. * - * This implementation creates an empty string buffer, appends a left - * brace, and iterates over the map's entrySet view, appending - * the string representation of each map.entry in turn. After - * appending each entry except the last, the string ", " is - * appended. Finally a right brace is appended. A string is obtained - * from the stringbuffer, and returned. - * - * @return a String representation of this map + * @return a string representation of this map */ public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{"); - Iterator> i = entrySet().iterator(); - boolean hasNext = i.hasNext(); - while (hasNext) { + if (! i.hasNext()) + return "{}"; + + StringBuilder sb = new StringBuilder(); + sb.append('{'); + for (;;) { Entry e = i.next(); K key = e.getKey(); - V value = e.getValue(); - if (key == this) - sb.append("(this Map)"); - else - sb.append(key); - sb.append("="); - if (value == this) - sb.append("(this Map)"); - else - sb.append(value); - hasNext = i.hasNext(); - if (hasNext) - sb.append(", "); - } - - sb.append("}"); - return sb.toString(); + V value = e.getValue(); + sb.append(key == this ? "(this Map)" : key); + sb.append('='); + sb.append(value == this ? "(this Map)" : value); + if (! i.hasNext()) + return sb.append('}').toString(); + sb.append(", "); + } } /** @@ -517,7 +530,7 @@ public abstract class AbstractMap i * Test for equality, checking for nulls. */ private static boolean eq(Object o1, Object o2) { - return (o1 == null ? o2 == null : o1.equals(o2)); + return o1 == null ? o2 == null : o1.equals(o2); } // Implementation Note: SimpleEntry and SimpleImmutableEntry @@ -534,9 +547,15 @@ public abstract class AbstractMap i * facilitates the process of building custom map * implementations. For example, it may be convenient to return * arrays of SimpleEntry instances in method - * Map.entrySet().toArray + * Map.entrySet().toArray. + * + * @since 1.6 */ - public static class SimpleEntry implements Entry { + public static class SimpleEntry + implements Entry, java.io.Serializable + { + private static final long serialVersionUID = -8499721149061103585L; + private final K key; private V value; @@ -594,6 +613,27 @@ public abstract class AbstractMap i return oldValue; } + /** + * Compares the specified object with this entry for equality. + * Returns {@code true} if the given object is also a map entry and + * the two entries represent the same mapping. More formally, two + * entries {@code e1} and {@code e2} represent the same mapping + * if

+	 *   (e1.getKey()==null ?
+	 *    e2.getKey()==null :
+	 *    e1.getKey().equals(e2.getKey()))
+	 *   &&
+	 *   (e1.getValue()==null ?
+	 *    e2.getValue()==null :
+	 *    e1.getValue().equals(e2.getValue()))
+ * This ensures that the {@code equals} method works properly across + * different implementations of the {@code Map.Entry} interface. + * + * @param o object to be compared for equality with this map entry + * @return {@code true} if the specified object is equal to this map + * entry + * @see #hashCode + */ public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; @@ -601,9 +641,22 @@ public abstract class AbstractMap i return eq(key, e.getKey()) && eq(value, e.getValue()); } + /** + * Returns the hash code value for this map entry. The hash code + * of a map entry {@code e} is defined to be:
+	 *   (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
+	 *   (e.getValue()==null ? 0 : e.getValue().hashCode())
+ * This ensures that {@code e1.equals(e2)} implies that + * {@code e1.hashCode()==e2.hashCode()} for any two Entries + * {@code e1} and {@code e2}, as required by the general + * contract of {@link Object#hashCode}. + * + * @return the hash code value for this map entry + * @see #equals + */ public int hashCode() { - return ((key == null) ? 0 : key.hashCode()) ^ - ((value == null) ? 0 : value.hashCode()); + return (key == null ? 0 : key.hashCode()) ^ + (value == null ? 0 : value.hashCode()); } /** @@ -621,12 +674,18 @@ public abstract class AbstractMap i } /** - * An Entry maintaining an immutable key and value, This class + * An Entry maintaining an immutable key and value. This class * does not support method setValue. This class may be * convenient in methods that return thread-safe snapshots of * key-value mappings. + * + * @since 1.6 */ - public static class SimpleImmutableEntry implements Entry { + public static class SimpleImmutableEntry + implements Entry, java.io.Serializable + { + private static final long serialVersionUID = 7138329143949025153L; + private final K key; private final V value; @@ -685,6 +744,27 @@ public abstract class AbstractMap i throw new UnsupportedOperationException(); } + /** + * Compares the specified object with this entry for equality. + * Returns {@code true} if the given object is also a map entry and + * the two entries represent the same mapping. More formally, two + * entries {@code e1} and {@code e2} represent the same mapping + * if
+	 *   (e1.getKey()==null ?
+	 *    e2.getKey()==null :
+	 *    e1.getKey().equals(e2.getKey()))
+	 *   &&
+	 *   (e1.getValue()==null ?
+	 *    e2.getValue()==null :
+	 *    e1.getValue().equals(e2.getValue()))
+ * This ensures that the {@code equals} method works properly across + * different implementations of the {@code Map.Entry} interface. + * + * @param o object to be compared for equality with this map entry + * @return {@code true} if the specified object is equal to this map + * entry + * @see #hashCode + */ public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; @@ -692,9 +772,22 @@ public abstract class AbstractMap i return eq(key, e.getKey()) && eq(value, e.getValue()); } + /** + * Returns the hash code value for this map entry. The hash code + * of a map entry {@code e} is defined to be:
+	 *   (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
+	 *   (e.getValue()==null ? 0 : e.getValue().hashCode())
+ * This ensures that {@code e1.equals(e2)} implies that + * {@code e1.hashCode()==e2.hashCode()} for any two Entries + * {@code e1} and {@code e2}, as required by the general + * contract of {@link Object#hashCode}. + * + * @return the hash code value for this map entry + * @see #equals + */ public int hashCode() { - return ((key == null) ? 0 : key.hashCode()) ^ - ((value == null) ? 0 : value.hashCode()); + return (key == null ? 0 : key.hashCode()) ^ + (value == null ? 0 : value.hashCode()); } /**