JDK

java.util.AbstractMapクラス

AbstractMapクラスはMapインタフェースを実装するクラスのスーパークラスとなる抽象クラスである。内部で定義されているインナークラスについては省略した。コンストラクタはprotectedとなっており,サブクラスからしか呼び出せない。put(K key, V value)メソッドはこのクラスではUnsupportedOperationExceptionをスローする実装となっており,サブクラスでオーバーライドする必要がある。内部の各要素(キーと値のペア)はjava.util.Map.Entry型のオブジェクトで管理されているようだ。

size()メソッドは,entrySet()メソッドで各要素のセットEntrySetを取得し,そのsize()メソッドを呼び出している。さらにisEmpty()メソッドはsize()メソッドの戻り値が0か否かで判定している。

containsValue(Object value)メソッドでは, entrySet()メソッドで各要素のセットEntrySetを取得し ,そのiterator()メソッドでイテレータを取得した上で,保持している要素を順次取り出して,値が一致するものがないかチェックしている。containsKey(Object key)メソッドもほぼ同じ実装であり,こちらはキーを使って検索している。

get(Object key)メソッドでも同じようにentrySet()メソッドで各要素のセットを取得し,そのイテレータを取得した上で順次要素を取り出し,キーが一致するオブジェクトを取得している。 remove(Object key)メソッドでも同様に順次検索を行って,見つかった要素を削除するというロジックである。

putAll(Map m)メソッドでは,引数のmapで与えられたキーと値のペア要素をすべて追加する。引数のマップのentrySet()ですべての要素を取り出し,拡張forループでループさせてすべてのキーと値をput(key, value)メソッドで追加している。

clear()メソッドでは,entrySet()メソッドで保持している要素のセットを取得して,そのclear()メソッドを実行する。

keySet()メソッドでは,メソッド内でAbstractSetを継承した無名インナークラスのインスタンスを作成して,それを返すようになっている。values()メソッドでも,メソッド内でAbstractCollectionを継承した無名インナークラスのインスタンスを作成して,それを返す実装である。なお,entrySet()メソッドは抽象メソッドになっている。

/*
 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.util;
import java.util.Map.Entry;
public abstract class AbstractMap<K,V> implements Map<K,V> {
    protected AbstractMap() {
    }
    // Query Operations
    public int size() {
        return entrySet().size();
    }
    public boolean isEmpty() {
        return size() == 0;
    }
    public boolean containsValue(Object value) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (value==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getValue()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (value.equals(e.getValue()))
                    return true;
            }
        }
        return false;
    }
    public boolean containsKey(Object key) {
        Iterator<Map.Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return true;
            }
        }
        return false;
    }
    public V get(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return e.getValue();
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return e.getValue();
            }
        }
        return null;
    }
    // Modification Operations
    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }
        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }
    // Bulk Operations
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }
    public void clear() {
        entrySet().clear();
    }
    // Views
    transient Set<K>        keySet;
    transient Collection<V> values;
    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new AbstractSet<K>() {
                public Iterator<K> iterator() {
                    return new Iterator<K>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();
                        public boolean hasNext() {
                            return i.hasNext();
                        }
                        public K next() {
                            return i.next().getKey();
                        }
                        public void remove() {
                            i.remove();
                        }
                    };
                }
                public int size() {
                    return AbstractMap.this.size();
                }
                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }
                public void clear() {
                    AbstractMap.this.clear();
                }
                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
            keySet = ks;
        }
        return ks;
    }
    public Collection<V> values() {
        Collection<V> vals = values;
        if (vals == null) {
            vals = new AbstractCollection<V>() {
                public Iterator<V> iterator() {
                    return new Iterator<V>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();
                        public boolean hasNext() {
                            return i.hasNext();
                        }
                        public V next() {
                            return i.next().getValue();
                        }
                        public void remove() {
                            i.remove();
                        }
                    };
                }
                public int size() {
                    return AbstractMap.this.size();
                }
                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }
                public void clear() {
                    AbstractMap.this.clear();
                }
                public boolean contains(Object v) {
                    return AbstractMap.this.containsValue(v);
                }
            };
            values = vals;
        }
        return vals;
    }
    public abstract Set<Entry<K,V>> entrySet();
    // Comparison and hashing
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Map))
            return false;
        Map<?,?> m = (Map<?,?>) o;
        if (m.size() != size())
            return false;
        try {
            for (Entry<K, V> e : entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {
                    if (!(m.get(key) == null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
        return true;
    }
    public int hashCode() {
        int h = 0;
        for (Entry<K, V> entry : entrySet())
            h += entry.hashCode();
        return h;
    }
    public String toString() {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (! i.hasNext())
            return "{}";
        StringBuilder sb = new StringBuilder();
        sb.append('{');
        for (;;) {
            Entry<K,V> e = i.next();
            K key = e.getKey();
            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(',').append(' ');
        }
    }
    protected Object clone() throws CloneNotSupportedException {
        AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
        result.keySet = null;
        result.values = null;
        return result;
    }
    private static boolean eq(Object o1, Object o2) {
        return o1 == null ? o2 == null : o1.equals(o2);
    }
    // Implementation Note: SimpleEntry and SimpleImmutableEntry
    // are distinct unrelated classes, even though they share
    // some code. Since you can't add or subtract final-ness
    // of a field in a subclass, they can't share representations,
    // and the amount of duplicated code is too small to warrant
    // exposing a common abstract class.
    public static class SimpleEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
省略
    }
    public static class SimpleImmutableEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
省略
    }
}