`
Donald_Draper
  • 浏览: 980202 次
社区版块
存档分类
最新评论

Map的简单实现AbstractMap

    博客分类:
  • JUC
 
阅读更多
package java.util;
import java.util.Map.Entry;

/**
 * This class provides a skeletal implementation of the <tt>Map</tt>
 * interface, to minimize the effort required to implement this interface.
 *
 AbstractMap提供了Map实现的一个基础框架,实现需要的最小功能。
 * <p>To implement an unmodifiable map, the programmer needs only to extend this
 * class and provide an implementation for the <tt>entrySet</tt> method, which
 * returns a set-view of the map's mappings.  Typically, the returned set
 * will, in turn, be implemented atop <tt>AbstractSet</tt>.  This set should
 * not support the <tt>add</tt> or <tt>remove</tt> methods, and its iterator
 * should not support the <tt>remove</tt> method.
 *
 为了提供一个unmodifiable map,编程者需要继承这个类,提供entrySet方法的实现,
 entrySet为提供一个Entry的视图set。set实现AbstractSet,这个不提供add和remove方法,
 同时iterator不支持iterator。

 * <p>To implement a modifiable map, the programmer must additionally override
 * this class's <tt>put</tt> method (which otherwise throws an
 * <tt>UnsupportedOperationException</tt>), and the iterator returned by
 * <tt>entrySet().iterator()</tt> must additionally implement its
 * <tt>remove</tt> method.
 *
 为了提供一个可修改的Map,开发者必须重写put方法,iterator返回通过entrySet().iterator(),
 同时实现iterator的remove方法,
 * <p>The programmer should generally provide a void (no argument) and map
 * constructor, as per the recommendation in the <tt>Map</tt> interface
 * specification.
 *
 建议开发者必须提供一个无参的构造函数
 * <p>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.
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see Map
 * @see Collection
 * @since 1.2
 */

public abstract class AbstractMap<K,V> implements Map<K,V> {
 /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractMap() {
    }
    //待子类扩展
    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    // Views

    /**
     * Each of these fields are initialized to contain an instance of the
     * appropriate view the first time this view is requested.  The views are
     * stateless, so there's no reason to create more than one of each.
     K,V视图集
     */
    transient volatile Set<K>        keySet = null;
    transient volatile Collection<V> values = null;
    //待子类扩展
    public abstract Set<Entry<K,V>> entrySet();
}

再来看Entry两个实现
public static class SimpleEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
        private static final long serialVersionUID = -8499721149061103585L;

        private final K key;//Final,不可变
        private V value;

        /**
         * Creates an entry representing a mapping from the specified
         * key to the specified value.
         *
         * @param key the key represented by this entry
         * @param value the value represented by this entry
         */
        public SimpleEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        /**
         * Creates an entry representing the same mapping as the
         * specified entry.
         *
         * @param entry the entry to copy
         */
        public SimpleEntry(Entry<? extends K, ? extends V> entry) {
            this.key   = entry.getKey();
            this.value = entry.getValue();
        }
	//设置新值,返回旧值
	 public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }
}

不可变的K-V对Entry
/**
     * An Entry maintaining an immutable key and value.  This class
     * does not support method <tt>setValue</tt>.  This class may be
     * convenient in methods that return thread-safe snapshots of
     * key-value mappings.
     *
     * @since 1.6
     */
    public static class SimpleImmutableEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
        private static final long serialVersionUID = 7138329143949025153L;

        private final K key;//final
        private final V value;//final

        /**
         * Creates an entry representing a mapping from the specified
         * key to the specified value.
         *
         * @param key the key represented by this entry
         * @param value the value represented by this entry
         */
        public SimpleImmutableEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        /**
         * Creates an entry representing the same mapping as the
         * specified entry.
         *
         * @param entry the entry to copy
         */
        public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
            this.key   = entry.getKey();
            this.value = entry.getValue();
        }
	public V setValue(V value) {
            throw new UnsupportedOperationException();
        }
}

不可变SimpleImmutableEntry,与一般的SimpleEntry的区别是Value为Final修饰,同时SetValue方法不可用。
由于put方法和k-v Entry Set的方法是待子类扩展的,我们来看看其他方法,get,remove,获取key和value的
视图集等;
//Map大小
 public int size() {
        return entrySet().size();
    }
//是否为null
 public boolean isEmpty() {
        return size() == 0;
    }
//是否包含value,遍历Entry,寻找值相等的
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;
    }
//是否包含key,遍历Entry,寻找key相等的
 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;
    }
//遍历Entry,寻找key对应的值
 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;
    }
//遍历Entry,寻找key对应的值,移除对应的k-v,Entry,返回值value
 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;
    }
//遍历Entry,将Map的Entry,放入到当前Map中
 public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }
//清空Map
 public void clear() {
        entrySet().clear();
    }
//返回Key视图set,遍历Entry,将Map的Entry的Key放入到Set中
 public Set<K> keySet() {
        if (keySet == null) {
            keySet = 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() {
			   //与AbstractMap相关联,从Map移除Entry
                            i.remove();
                        }
                    };
                }

                public int size() {
		//与AbstractMap相关联
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
		//与AbstractMap相关联
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
		//与AbstractMap相关联
                    AbstractMap.this.clear();
                }

                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
        }
        return keySet;
    }

从上面可以看出Key视图set的所有操作都是与AbstractMap相关联,可以理解,
直接是AbstractMap的操作。
//获取values的视图Collection
public Collection<V> values() {
        if (values == null) {
            values = 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);
                }
            };
        }
        return values;
    }

这个与Key视图Set类似,不再讲。
//判断与Object是否相等,首先判断是否为Map,再判断Size是否相等,
再遍历Entry,对的Key是否存在,Value是否相等。
public boolean equals(Object o) {
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<K,V> m = (Map<K,V>) o;
        if (m.size() != size())
            return false;

        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                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;
    }
 //所有Entry的Hash值和
 public int hashCode() {
        int h = 0;
        Iterator<Entry<K,V>> i = entrySet().iterator();
        while (i.hasNext())
            h += i.next().hashCode();
        return h;
    }
//克隆,调用的是父类的clone,克隆后key,value为null
    protected Object clone() throws CloneNotSupportedException {
        AbstractMap<K,V> result = (AbstractMap<K,V>)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);
    }

总结:
AbstractMap提供了一个Map的简单实现,不过没有提供put的entrySet方法,这个待子类扩展。Key视图set的所有操作都是与AbstractMap相关联,可以理解,直接是AbstractMap的操作;Value的视图Collection,同样。不可变SimpleImmutableEntry,与一般的SimpleEntry的区别是Value为Final修饰,同时SetValue方法不可用。
0
0
分享到:
评论

相关推荐

    详解Java中AbstractMap抽象类

    AbstractMap抽象类是Java集合框架中的一个重要组件,为Map接口提供了一个骨架实现。它提供了一些简单且通用的方法,但其中有两个方法非常值得关注,即keySet和values方法。这些方法的源码实现可以说是教科书式的典范...

    Map、Set、Iterator迭代详解

    - **AbstractMap**: `Map`的抽象基类。 #### 4. 实现类举例 - **ArrayList**: 基于数组的`List`实现。 - **LinkedList**: 基于链表的`List`实现。 - **HashSet**: 基于哈希表的`Set`实现。 - **TreeSet**: 基于红黑...

    java collections design.pdf

    4. 抽象实现:如AbstractList、AbstractSet和AbstractMap,提供部分实现,帮助开发者快速构建自己的集合实现。 总的来说,Java集合框架是Java开发中不可或缺的一部分,它为开发者提供了强大而灵活的数据管理工具,...

    JAVA集合框架

    - 抽象类如`AbstractCollection`、`AbstractList`和`AbstractMap`为自定义集合类提供了一些默认实现,降低了开发者的实现难度。 - 实现类如`ArrayList`、`LinkedList`、`HashMap`等提供了具体的存储和操作机制。 ...

    浅析Java中Map与HashMap,Hashtable,HashSet的区别

    `HashMap`、`Hashtable`和`HashSet`都是基于`Map`或`Set`接口实现的不同数据结构,它们在功能、线程安全性和性能等方面有显著差异。 首先,`HashMap`和`Hashtable`都实现了`Map`接口,这意味着它们都可以存储键值对...

    Java 集合框架+集合实例

    - **AbstractMap**:实现了Map接口的一部分。 3. **实现类**: - **LinkedList**:实现了List接口,使用链表结构存储元素,支持快速的插入和删除操作。 - **ArrayList**:实现了List接口,基于动态数组,适合...

    Java集合框架.ppt

    AbstractCollection、AbstractList、AbstractSet和AbstractMap等抽象类提供了接口的一些默认实现,方便开发者创建自定义集合类。还有一些实现类,如ArrayList、LinkedList、HashSet、HashMap等,它们提供了常用的...

    Java6 Collection Framework 新特性概览.pdf

    - **定义**:这两个类分别提供了可变和不可变的Map.Entry实现。 - **特点**: - `SimpleEntry` 支持键值对的动态修改。 - `SimpleImmutableEntry` 则不允许修改键值对,确保了数据的一致性。 #### 3. 存在类的...

    hashmap.zip

    在Java编程语言中,HashMap是一种常用的集合类,它实现了Map接口,用于存储键值对(key-value pairs)。HashMap的工作基于哈希表数据结构,提供快速的插入、删除和查找操作。下面我们将深入探讨HashMap的实现原理,...

    阿里Java最新版面试集锦2021.pdf

    - `HashMap`继承自`AbstractMap`,实现了`Map`, `Cloneable`, `Serializable`接口。 - `HashTable`继承自`Dictionary`,同样实现了`Map`, `Cloneable`, `Serializable`接口。 #### 2. 线程安全性 - `HashTable`是...

    php设计模式之组合模式实例详解【星际争霸游戏案例】

    虽然在实际的地图类`Map`中,这些方法不需要实现,但为了组合模式的统一性,它们依然存在。 接着,我们创建了两个具体的类:`Map`和`MapBag`。`Map`类代表单个地图,不包含子对象,因此其`getChildren`、`addChild`...

    Java高频面试题汇总(精华版).pdf

    若需线程安全版本,可通过`Collections.synchronizedMap(new HashMap())`实现。 - **ConcurrentHashMap**: 线程安全,通过内部使用锁分段机制来提高并发性能。 ##### 3. Key/Value是否允许为空 - **Hashtable**: ...

    面试总结篇(一年多工作经验).docx

    - `Hashtable`继承自`Dictionary`类,`HashMap`继承自`AbstractMap`,两者都实现了`Map`接口。 - 线程安全:`Hashtable`的方法是同步的,适合多线程环境,而`HashMap`在默认情况下是非同步的,适合单线程环境。 -...

    sesvc.exe 阿萨德

    Note that AbstractMap fields are used * for keySet() and values(). */ transient Set&lt;Map.Entry,V&gt;&gt; entrySet; /** * The number of key-value mappings contained in this map. */ transient int size; 和...

    阿里面试集锦

    - `HashMap`继承自`AbstractMap`,实现了`Map`接口,并且还实现了`Cloneable`和`Serializable`接口。 - `Hashtable`继承自`Dictionary`,同样实现了`Map`接口,并且同样实现了`Cloneable`和`Serializable`接口。 ...

    java面试题——详解HashMap和Hashtable 的区别

    - `Hashtable` 直接继承自 `Dictionary` 类,而 `HashMap` 继承自 `AbstractMap`,并实现了 `Map` 接口。这使得 `HashMap` 更加符合面向对象的设计原则,且可以利用抽象类的一些特性,如 `AbstractMap` 提供了部分...

    java类职位应聘面试题集

    - **接口与抽象类**:对比List、Set和Map接口与AbstractList、AbstractSet和AbstractMap抽象类的区别。 - **泛型**:使用泛型提高代码安全性,理解类型擦除。 3. **字符串操作**: - **String对象不可变性**:...

Global site tag (gtag.js) - Google Analytics