jaroslav@557: /* jaroslav@557: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. jaroslav@557: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@557: * jaroslav@557: * This code is free software; you can redistribute it and/or modify it jaroslav@557: * under the terms of the GNU General Public License version 2 only, as jaroslav@557: * published by the Free Software Foundation. Oracle designates this jaroslav@557: * particular file as subject to the "Classpath" exception as provided jaroslav@557: * by Oracle in the LICENSE file that accompanied this code. jaroslav@557: * jaroslav@557: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@557: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@557: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@557: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@557: * accompanied this code). jaroslav@557: * jaroslav@557: * You should have received a copy of the GNU General Public License version jaroslav@557: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@557: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@557: * jaroslav@557: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@557: * or visit www.oracle.com if you need additional information or have any jaroslav@557: * questions. jaroslav@557: */ jaroslav@557: jaroslav@557: package java.util; jaroslav@557: import java.util.Map.Entry; jaroslav@557: jaroslav@557: /** jaroslav@557: * This class provides a skeletal implementation of the Map jaroslav@557: * interface, to minimize the effort required to implement this interface. jaroslav@557: * jaroslav@557: *
To implement an unmodifiable map, the programmer needs only to extend this jaroslav@557: * class and provide an implementation for the entrySet method, which jaroslav@557: * returns a set-view of the map's mappings. Typically, the returned set jaroslav@557: * will, in turn, be implemented atop AbstractSet. This set should jaroslav@557: * not support the add or remove methods, and its iterator jaroslav@557: * should not support the remove method. jaroslav@557: * jaroslav@557: *
To implement a modifiable map, the programmer must additionally override jaroslav@557: * this class's put method (which otherwise throws an jaroslav@557: * UnsupportedOperationException), and the iterator returned by jaroslav@557: * entrySet().iterator() must additionally implement its jaroslav@557: * remove method. jaroslav@557: * jaroslav@557: *
The programmer should generally provide a void (no argument) and map jaroslav@557: * constructor, as per the recommendation in the Map interface jaroslav@557: * specification. jaroslav@557: * jaroslav@557: *
The documentation for each non-abstract method in this class describes its jaroslav@557: * implementation in detail. Each of these methods may be overridden if the jaroslav@557: * map being implemented admits a more efficient implementation. jaroslav@557: * jaroslav@557: *
This class is a member of the
jaroslav@557: *
jaroslav@557: * Java Collections Framework.
jaroslav@557: *
jaroslav@557: * @param This implementation returns entrySet().size().
jaroslav@557: */
jaroslav@557: public int size() {
jaroslav@557: return entrySet().size();
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * {@inheritDoc}
jaroslav@557: *
jaroslav@557: * This implementation returns size() == 0.
jaroslav@557: */
jaroslav@557: public boolean isEmpty() {
jaroslav@557: return size() == 0;
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * {@inheritDoc}
jaroslav@557: *
jaroslav@557: * This implementation iterates over entrySet() searching
jaroslav@557: * for an entry with the specified value. If such an entry is found,
jaroslav@557: * true is returned. If the iteration terminates without
jaroslav@557: * finding such an entry, false is returned. Note that this
jaroslav@557: * implementation requires linear time in the size of the map.
jaroslav@557: *
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public boolean containsValue(Object value) {
jaroslav@557: Iterator This implementation iterates over entrySet() searching
jaroslav@557: * for an entry with the specified key. If such an entry is found,
jaroslav@557: * true is returned. If the iteration terminates without
jaroslav@557: * finding such an entry, false is returned. Note that this
jaroslav@557: * implementation requires linear time in the size of the map; many
jaroslav@557: * implementations will override this method.
jaroslav@557: *
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public boolean containsKey(Object key) {
jaroslav@557: Iterator This implementation iterates over entrySet() searching
jaroslav@557: * for an entry with the specified key. If such an entry is found,
jaroslav@557: * the entry's value is returned. If the iteration terminates without
jaroslav@557: * finding such an entry, null is returned. Note that this
jaroslav@557: * implementation requires linear time in the size of the map; many
jaroslav@557: * implementations will override this method.
jaroslav@557: *
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public V get(Object key) {
jaroslav@557: Iterator This implementation always throws an
jaroslav@557: * UnsupportedOperationException.
jaroslav@557: *
jaroslav@557: * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: * @throws IllegalArgumentException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public V put(K key, V value) {
jaroslav@557: throw new UnsupportedOperationException();
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * {@inheritDoc}
jaroslav@557: *
jaroslav@557: * This implementation iterates over entrySet() searching for an
jaroslav@557: * entry with the specified key. If such an entry is found, its value is
jaroslav@557: * obtained with its getValue operation, the entry is removed
jaroslav@557: * from the collection (and the backing map) with the iterator's
jaroslav@557: * remove operation, and the saved value is returned. If the
jaroslav@557: * iteration terminates without finding such an entry, null is
jaroslav@557: * returned. Note that this implementation requires linear time in the
jaroslav@557: * size of the map; many implementations will override this method.
jaroslav@557: *
jaroslav@557: * Note that this implementation throws an
jaroslav@557: * UnsupportedOperationException if the entrySet
jaroslav@557: * iterator does not support the remove method and this map
jaroslav@557: * contains a mapping for the specified key.
jaroslav@557: *
jaroslav@557: * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public V remove(Object key) {
jaroslav@557: Iterator This implementation iterates over the specified map's
jaroslav@557: * entrySet() collection, and calls this map's put
jaroslav@557: * operation once for each entry returned by the iteration.
jaroslav@557: *
jaroslav@557: * Note that this implementation throws an
jaroslav@557: * UnsupportedOperationException if this map does not support
jaroslav@557: * the put operation and the specified map is nonempty.
jaroslav@557: *
jaroslav@557: * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@557: * @throws ClassCastException {@inheritDoc}
jaroslav@557: * @throws NullPointerException {@inheritDoc}
jaroslav@557: * @throws IllegalArgumentException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public void putAll(Map extends K, ? extends V> m) {
jaroslav@557: for (Map.Entry extends K, ? extends V> e : m.entrySet())
jaroslav@557: put(e.getKey(), e.getValue());
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * {@inheritDoc}
jaroslav@557: *
jaroslav@557: * This implementation calls entrySet().clear().
jaroslav@557: *
jaroslav@557: * Note that this implementation throws an
jaroslav@557: * UnsupportedOperationException if the entrySet
jaroslav@557: * does not support the clear operation.
jaroslav@557: *
jaroslav@557: * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@557: */
jaroslav@557: public void clear() {
jaroslav@557: entrySet().clear();
jaroslav@557: }
jaroslav@557:
jaroslav@557:
jaroslav@557: // Views
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * Each of these fields are initialized to contain an instance of the
jaroslav@557: * appropriate view the first time this view is requested. The views are
jaroslav@557: * stateless, so there's no reason to create more than one of each.
jaroslav@557: */
jaroslav@557: transient volatile Set This implementation returns a set that subclasses {@link AbstractSet}.
jaroslav@557: * The subclass's iterator method returns a "wrapper object" over this
jaroslav@557: * map's entrySet() iterator. The size method
jaroslav@557: * delegates to this map's size method and the
jaroslav@557: * contains method delegates to this map's
jaroslav@557: * containsKey method.
jaroslav@557: *
jaroslav@557: * The set is created the first time this method is called,
jaroslav@557: * and returned in response to all subsequent calls. No synchronization
jaroslav@557: * is performed, so there is a slight chance that multiple calls to this
jaroslav@557: * method will not all return the same set.
jaroslav@557: */
jaroslav@557: public Set This implementation returns a collection that subclasses {@link
jaroslav@557: * AbstractCollection}. The subclass's iterator method returns a
jaroslav@557: * "wrapper object" over this map's entrySet() iterator.
jaroslav@557: * The size method delegates to this map's size
jaroslav@557: * method and the contains method delegates to this map's
jaroslav@557: * containsValue method.
jaroslav@557: *
jaroslav@557: * The collection is created the first time this method is called, and
jaroslav@557: * returned in response to all subsequent calls. No synchronization is
jaroslav@557: * performed, so there is a slight chance that multiple calls to this
jaroslav@557: * method will not all return the same collection.
jaroslav@557: */
jaroslav@557: public Collection This implementation first checks if the specified object is this map;
jaroslav@557: * if so it returns true. Then, it checks if the specified
jaroslav@557: * object is a map whose size is identical to the size of this map; if
jaroslav@557: * not, it returns false. If so, it iterates over this map's
jaroslav@557: * entrySet collection, and checks that the specified map
jaroslav@557: * contains each mapping that this map contains. If the specified map
jaroslav@557: * fails to contain such a mapping, false is returned. If the
jaroslav@557: * iteration completes, true is returned.
jaroslav@557: *
jaroslav@557: * @param o object to be compared for equality with this map
jaroslav@557: * @return true if the specified object is equal to this map
jaroslav@557: */
jaroslav@557: public boolean equals(Object o) {
jaroslav@557: if (o == this)
jaroslav@557: return true;
jaroslav@557:
jaroslav@557: if (!(o instanceof Map))
jaroslav@557: return false;
jaroslav@557: Map This implementation iterates over entrySet(), calling
jaroslav@557: * {@link Map.Entry#hashCode hashCode()} on each element (entry) in the
jaroslav@557: * set, and adding up the results.
jaroslav@557: *
jaroslav@557: * @return the hash code value for this map
jaroslav@557: * @see Map.Entry#hashCode()
jaroslav@557: * @see Object#equals(Object)
jaroslav@557: * @see Set#equals(Object)
jaroslav@557: */
jaroslav@557: public int hashCode() {
jaroslav@557: int h = 0;
jaroslav@557: Iterator
jaroslav@557: * (e1.getKey()==null ?
jaroslav@557: * e2.getKey()==null :
jaroslav@557: * e1.getKey().equals(e2.getKey()))
jaroslav@557: * &&
jaroslav@557: * (e1.getValue()==null ?
jaroslav@557: * e2.getValue()==null :
jaroslav@557: * e1.getValue().equals(e2.getValue()))
jaroslav@557: * This ensures that the {@code equals} method works properly across
jaroslav@557: * different implementations of the {@code Map.Entry} interface.
jaroslav@557: *
jaroslav@557: * @param o object to be compared for equality with this map entry
jaroslav@557: * @return {@code true} if the specified object is equal to this map
jaroslav@557: * entry
jaroslav@557: * @see #hashCode
jaroslav@557: */
jaroslav@557: public boolean equals(Object o) {
jaroslav@557: if (!(o instanceof Map.Entry))
jaroslav@557: return false;
jaroslav@557: Map.Entry e = (Map.Entry)o;
jaroslav@557: return eq(key, e.getKey()) && eq(value, e.getValue());
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * Returns the hash code value for this map entry. The hash code
jaroslav@557: * of a map entry {@code e} is defined to be:
jaroslav@557: * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
jaroslav@557: * (e.getValue()==null ? 0 : e.getValue().hashCode())
jaroslav@557: * This ensures that {@code e1.equals(e2)} implies that
jaroslav@557: * {@code e1.hashCode()==e2.hashCode()} for any two Entries
jaroslav@557: * {@code e1} and {@code e2}, as required by the general
jaroslav@557: * contract of {@link Object#hashCode}.
jaroslav@557: *
jaroslav@557: * @return the hash code value for this map entry
jaroslav@557: * @see #equals
jaroslav@557: */
jaroslav@557: public int hashCode() {
jaroslav@557: return (key == null ? 0 : key.hashCode()) ^
jaroslav@557: (value == null ? 0 : value.hashCode());
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * Returns a String representation of this map entry. This
jaroslav@557: * implementation returns the string representation of this
jaroslav@557: * entry's key followed by the equals character ("=")
jaroslav@557: * followed by the string representation of this entry's value.
jaroslav@557: *
jaroslav@557: * @return a String representation of this map entry
jaroslav@557: */
jaroslav@557: public String toString() {
jaroslav@557: return key + "=" + value;
jaroslav@557: }
jaroslav@557:
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * An Entry maintaining an immutable key and value. This class
jaroslav@557: * does not support method setValue. This class may be
jaroslav@557: * convenient in methods that return thread-safe snapshots of
jaroslav@557: * key-value mappings.
jaroslav@557: *
jaroslav@557: * @since 1.6
jaroslav@557: */
jaroslav@557: public static class SimpleImmutableEntry
jaroslav@557: * (e1.getKey()==null ?
jaroslav@557: * e2.getKey()==null :
jaroslav@557: * e1.getKey().equals(e2.getKey()))
jaroslav@557: * &&
jaroslav@557: * (e1.getValue()==null ?
jaroslav@557: * e2.getValue()==null :
jaroslav@557: * e1.getValue().equals(e2.getValue()))
jaroslav@557: * This ensures that the {@code equals} method works properly across
jaroslav@557: * different implementations of the {@code Map.Entry} interface.
jaroslav@557: *
jaroslav@557: * @param o object to be compared for equality with this map entry
jaroslav@557: * @return {@code true} if the specified object is equal to this map
jaroslav@557: * entry
jaroslav@557: * @see #hashCode
jaroslav@557: */
jaroslav@557: public boolean equals(Object o) {
jaroslav@557: if (!(o instanceof Map.Entry))
jaroslav@557: return false;
jaroslav@557: Map.Entry e = (Map.Entry)o;
jaroslav@557: return eq(key, e.getKey()) && eq(value, e.getValue());
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * Returns the hash code value for this map entry. The hash code
jaroslav@557: * of a map entry {@code e} is defined to be:
jaroslav@557: * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
jaroslav@557: * (e.getValue()==null ? 0 : e.getValue().hashCode())
jaroslav@557: * This ensures that {@code e1.equals(e2)} implies that
jaroslav@557: * {@code e1.hashCode()==e2.hashCode()} for any two Entries
jaroslav@557: * {@code e1} and {@code e2}, as required by the general
jaroslav@557: * contract of {@link Object#hashCode}.
jaroslav@557: *
jaroslav@557: * @return the hash code value for this map entry
jaroslav@557: * @see #equals
jaroslav@557: */
jaroslav@557: public int hashCode() {
jaroslav@557: return (key == null ? 0 : key.hashCode()) ^
jaroslav@557: (value == null ? 0 : value.hashCode());
jaroslav@557: }
jaroslav@557:
jaroslav@557: /**
jaroslav@557: * Returns a String representation of this map entry. This
jaroslav@557: * implementation returns the string representation of this
jaroslav@557: * entry's key followed by the equals character ("=")
jaroslav@557: * followed by the string representation of this entry's value.
jaroslav@557: *
jaroslav@557: * @return a String representation of this map entry
jaroslav@557: */
jaroslav@557: public String toString() {
jaroslav@557: return key + "=" + value;
jaroslav@557: }
jaroslav@557:
jaroslav@557: }
jaroslav@557:
jaroslav@557: }