HashMap源码实现

来源:互联网 发布:石家庄蓝点网络 编辑:程序博客网 时间:2024/06/18 08:37

HashMap存储格式

首先来看看HashMap的数据存储格式:
这里写图片描述

从本质上来说,hashMap实际上是一个数组,数组的每个元素称为一个Node,这个Node实际上是一个链表,每个对象的hash值经过一些处理作为数组的key,hashMap通过key定位到数组对应的位置。当两个对象的hash值相同的时候,就会在链表的next元素进行拓展。

源码

本文主要要实现hashMap的put、get、扩容方法;
基本代码架构:

public class MyHashMap<K,V> {    //数组的初始大小    static final int DEFAULR_INITIAL_CAPACITY=16;    //安全因子    static final float DEFAULT_LOAD_FACTOR = 0.75f;    //扩容因子    static final int DEFAULT_DITATATION_FACROT=2;    private int size = 0;    //数组元素    private Node<K,V> table[] = null;    public V put(){        return null;    };    public V get(){        return null;    }    //Map的大小    public int size(){        return this.size;    }    //提供hash算法,确定Node在数组中的位置    private int indexOf(Object o){        return 0;    }    //扩容方法    private void dilatation() {     }    public class Node<K,V> implements Entry<K, V>{        @Override        public K getKey() {            return null;        }        @Override        public V getValue() {            return null;        }        @Override        public V setValue(V value) {            return null;        }    }}

关于构造

前面已经说过,数组的元素是由节点Node

private class Node<K,V> implements Entry<K, V>{        //Node在数组中的位置,根据对象的hash值确定        private int index;        private K key;        private V value;        //当hash值出现冲突以后,往链表中插入对象        private Node<K,V> next;        public Node(int index, K key, V value, Node<K, V> next) {            super();            this.index = index;            this.key = key;            this.value = value;            this.next = next;        }        @Override        public K getKey() {            return null;        }        @Override        public V getValue() {            return null;        }        @Override        public V setValue(V value) {            return null;        }    }

下面来看看HashMap的构造:

private Node<K,V> table[] = null;    //创建一个大小为默认值的数组    public MyHashMap() {        table = new Node[DEFAULR_INITIAL_CAPACITY];    }

hash算法indexOf方法实现:

//提供hash算法,确定Node在数组中的位置    public int indexOf(K  key){        //与数组length-1取模,确定返回值不大于数组的length-1        return hash(key) % (table.length-1);    }    //让hash值无符号右移16位,缩小hash值    static final int hash(Object key) {        int h;        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);    }

源码实现

put方法实现:

public V put(K key,V value){        //tab用来指向table,p当前数组位置的Node;        Node<K, V> tab[] = table;         Node<K,V> p;        int i = indexOf(key);        p = table[i];        if(p == null){            //如果数组的该位置没有元素            p = new Node<K, V>(i, key, value, null);            tab[i] = p;            return value;        }else{            //如果数组的该位置有元素            Node<K,V> e;//用于判断key是否相同,是否需要覆盖            if(p.index == indexOf(key)&&(p.key==key||key.equals(p.key))){                //key相同(这里我们可以看到map判断key是否相同需要他的hash值和equals都相同)                e = p;            }else{                //对p进行遍历                for(int count = 0 ; ; ++count){                    if((e=p.next)==null){                        //如果p链表没有后续元素                        p.next = new Node<K,V>(indexOf(key), key, value, null);                        break;                    }                    //如果链表中其他元素的key有相同的                    if(e.index==indexOf(key)&&(e.key==key||e.key.equals(key))){                        break;                    }                    //如果链表有后续元素,并且key和链表当前位置的元素key不用,将p指向p.next                    p= e;                }            }            //key有覆盖的情况出现,将key对应的value进行覆盖处理            if(e!=null){                e.value = value;                return value;            }            //e==null则没有覆盖情况            size++;            if(size>DEFAULR_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR){                //扩容;                dilatation();            }        }        return value;    };

get方法实现:

public V get(K key){        Node<K,V> tab[] ; Node<K,V> e ;        tab = table;        int index = indexOf(key);        e = tab[index];        //该key没有值        if(e == null){            return null;        }else{            //遍历Node e            do {                //获取e的值                if(key==e.key||key.equals(e.key)){                    return e.value;                }            } while ((e=e.next)!=null);        }        return null;    }

扩容方法dilatation

    //扩容方法    private void dilatation() {        Node<K, V> oldNode[] = table;        int oldCount = table.length;        //将容量扩张到两倍        int newCount = oldCount*DEFAULT_DITATATION_FACROT;        Node<K, V> newNode[] = new Node[newCount];        table = newNode;        for(int i = 0 ; i < oldCount ; i++){            if(oldNode[i]!=null){                Node<K,V> e = oldNode[i];                Node<K,V> tmp = oldNode[i];                //给newNode赋值,修改Node的index值                int newIndex = indexOf(tmp.getKey());                do {                    tmp.index = newIndex;                } while ((tmp=tmp.next)!=null);                newNode[newIndex] = e;            }        }    }
1 0
原创粉丝点击