常用容器(Collection)实现类总结——HashMap

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用容器(Collection)实现类总结——HashMap相关的知识,希望对你有一定的参考价值。

 

HashMap简略说明:

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 

(Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.  )

此实现假定哈希函数将元素适当地分布在各桶(buckets)之间,可为基本操作(getput)提供稳定的性能。迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。 

(This implementation provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets. Iteration over collection views requires time proportional to the "capacity" of the HashMap instance (the number of buckets) plus its size (the number of key-value mappings). Thus, it‘s very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important. )

 

HashMap的优、缺点分析:

优点:

  • 通过键值对(key-value)而构成一对一(也可以是一对多)的映射关系,方便数据的查询
  • 由于HashMap只允许唯一键的存在,所以查询速度较快

缺点:

  • 映射无序,且不保证顺序恒定

 

基本实现:

  • Entry类的实现:

    class Entry {
        Object key;
        Object value;
        
        public Entry() {}
        
        public Entry(Object key, Object value) {
            super();
            this.key = key;
            this.value = value;
        }
    }

    HashMap操作的是键值对,需要一个Entry类来实现

 

  • MyHashMap类的简单实现:

    public class MyHashMap {
        Entry[] arr = new Entry[100];
        int size;
        
        public void put(Object key, Object value) {
            Entry e = new Entry(key, value);
            for(int i = 0;i < size; i++) {
                if(arr[i].key.equals(key)) {
                    arr[i].value = value;
                    return ;
                }
            }                            //由于HashMap只允许存在唯一键,重复的键值对会被新值覆盖,所以引入这段代码
            arr[size++] = e;
        }
        
        public Object get(Object key) {
            for(int i = 0;i < size; i++) {
                if(arr[i].key.equals(key)) {
                    return arr[i].value;
                }
            }
            return null;
        }
        
        public void remove(Object key) {
            for(int i = 0;i < size; i++) {
                if(arr[i].key.equals(key)) {
                    arr[i].value = null;
                    size--;
                }
            }
        }
        
        public boolean containsKey(Object key) {
            for(int i = 0;i < size; i++) {
                if(arr[i].key.equals(key)) {
                    return true;
                }
            }
            return false;
        }
        
        public boolean containsValue(Object value) {
            for(int i = 0;i < size; i++) {
                if(arr[i].value.equals(value)) {
                    return true;
                }
            }
            return false;
        }
        
        public int getSize() {
            return size;
        }
    
        public void setSize(int size) {
            this.size = size;
        }

    显然,基本实现HashMap的方法效率低下,需要改进

改进版:

实际上,HashMap的底层实现是通过Array和LinkedList共同实现的,所以HashMap综合了两者的优点,实现的关键在于利用hashcode:

//存储时:
int hash = key.hashCode();
int index = hash % Entry[].length;
Entry[index] = value;

//取值时:
int hash = key.hashCode();
int index = hash % Entry[].length;
return Entry[index];

HashMap实现的图片说明:

技术分享

技术分享

  • Entry类的升级:

    class Entry<K,V>{
        final K key;
        V value;
        Entry<K,V> next;//下一个结点
     
        public Entry(K key, V value, Entry<K, V> next) {
            super();
            this.key = key;
            this.value = value;
            this.next = next;
        }
    
        public final K getKey() {
            return key;
        }
    
        public final V getValue() {
            return value;
        }
    
        public final V setValue(V newValue) {
        V oldValue = value;
            value = newValue;
            return oldValue;
        }
    }

     

  • MyHashMap类的实现:

    public class MyHashMap<K, V> {
        private Entry[] table;
        static final int DEFAULT_INITIAL_CAPACITY = 16;//默认数组长度
        private int size;
    
        public Hash() {
            table = new Entry[DEFAULT_INITIAL_CAPACITY];
            size = DEFAULT_INITIAL_CAPACITY;
        }
    
        public int getSize() {
            return size;
        }
        
        // 求index
        static int indexFor(int h, int length) {
            return h % (length - 1);
        }
    
        //获取value
        public V get(Object key) {
            if (key == null)
                return null;
            int hash = key.hashCode();
            int index = indexFor(hash, table.length);// 求key在数组中的下标
            for (Entry<K, V> e = table[index]; e != null; e = e.next) {
                Object k = e.key;
                if (e.key.hashCode() == hash && (k == key || key.equals(k)))
                    return e.value;
            }
            return null;
        }
    
        public V put(K key, V value) {
            if (key == null)
                return null;
            int hash = key.hashCode();
            int index = indexFor(hash, table.length);
    
            for (Entry<K, V> e = table[index]; e != null; e = e.next) {
                Object k = e.key;
                if (e.key.hashCode() == hash && (k == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                    return oldValue;
                }
            }
            // 如果key值不存在,那么需要添加
            Entry<K, V> e = table[index];// 获取当前数组中的e
            table[index] = new Entry<K, V>(key, value, e);// 新建一个Entry,并将其指向原先的e
            return null;
        }
    }

 

以上是关于常用容器(Collection)实现类总结——HashMap的主要内容,如果未能解决你的问题,请参考以下文章

常用容器(Collection)实现类总结——HashMap

常用的几种java集合类总结

JavaSE高阶知识总结

Java集合总结:列表和队列

基础总结/集合/collection总结

Java中的集合框架大总结