读书人

Java学习之HashMap: 怎么正确实现Map的

发布时间: 2012-12-19 14:13:14 作者: rapoo

Java学习之HashMap: 如何正确实现Map的entrySet()方法

通过继承AbstractMap我们可以很容易实现自己的Map,我们只需要实现唯一的抽象的entrySet()方法。 以下是来自《Jav编程思想》(第四版第17章的例子),继承AbstractMap实现了自己的SlowMap。 另外还应该注意, 如果要创建自己的Map,还必须同时定义Map.Entry的实现。

?

总结起来实现自定义Map需要以下两个步骤:

    继承AbstractMap需要实现entrySet()方法实现自己的Map.Entry

?

?以上是一个参考实现。这个解决方案看起来很简单并且没什么问题,但这并不是一个恰当的实现。主要问题是它创建了键和值的副本。entrySet()的恰当实现 应该在Map中提供视图,而不是副本,并且这个视图允许对原始的映射表进行修改,而副本则不行。

?

可以参考源码来学习正确的entrySet()应该如何实现。首先先看Map中entrySet()的声明

    public Set<Map.Entry<K,V>> entrySet() {return entrySet0();    }    private Set<Map.Entry<K,V>> entrySet0() {        Set<Map.Entry<K,V>> es = entrySet;        return es != null ? es : (entrySet = new EntrySet());    }    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {        public Iterator<Map.Entry<K,V>> iterator() {            return newEntryIterator();        }        public boolean contains(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry<K,V> e = (Map.Entry<K,V>) o;            Entry<K,V> candidate = getEntry(e.getKey());            return candidate != null && candidate.equals(e);        }        public boolean remove(Object o) {            return removeMapping(o) != null;        }        public int size() {            return size;        }        public void clear() {            HashMap.this.clear();        }    }

?EntrySet是HashMap的一个内部类,它继承自AbstractSet,必须需要实现iterator()和size()两个抽象方法。而HashMap的entrySet()不过是返回了EntrySet的一个实例。

注意,与我们之前定义的SlowMap的entrySet()相比,这里的entrySet()实现中没有进行任何创建副本的操作。不难发现,remove()和clear()等方法,最终会调用到EntrySet所在的外部对象(即一个HashMap实例)的相关方法,从而实现对Map的修改应该会反映到这个Set,反过来对这个Set的修改也会反映到Map。当然,除了直接在entrySet()方法返回的Set对象上直接进行操作,还可以获取这个Set的迭代器,通过迭代器来修改Map和对应的Set。这类修改,同样也应当需要实现对Map的修改应该会反映到这个Set,反过来对这个Set的修改也会反映到Map。这里涉及到HashMap.EntryIterator类,内容较多,后面接着分析

?

读书人网 >编程

热点推荐