手写HashMap(数组+链表;可扩容;指定table最大长度)

手写HashMap(数组+链表;可扩容;指定table最大长度)

看过HashMap后,心血来潮,凭感觉写了这个“青春版”HashMap。
虽然只有数组+链表,但是有那么个形状了。
简单测试已经是没什么问题,后续会改进。


import org.apache.commons.lang.NullArgumentException;

import java.io.Serializable;
import java.util.*;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/3/29 20:44
 */

/**
 * 模仿HashMap 手写一个自己的简单HashMap
 * 简单测试过
 * @param <K>
 * @param <V>
 */
public class SimpleHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> , Cloneable , Serializable {

    private static final long serialVersionUID = 1L ;

    private transient int size ;

    private transient long modCount ;

    private transient Node<K,V> table[] ;

    private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4 ;

    private static final int MAX_CAPACITY = 1 << 30 ;

    private static final float DEFAULT_LOAD_FACTOR = 0.75f ;

    private int maxCapacity ;

    private final float loadFactor ;

    private int threshold ;

    private transient Set<K> keySet ;

    private transient Set<Map.Entry<K,V>> entrySet ;

    //----------------------------Constructor---------------------------------

    public SimpleHashMap(){
        this(DEFAULT_INITIAL_CAPACITY , DEFAULT_LOAD_FACTOR , MAX_CAPACITY) ;
    }

    public SimpleHashMap(int initialCapacity){
        this(initialCapacity , DEFAULT_LOAD_FACTOR , MAX_CAPACITY) ;
    }

    public SimpleHashMap(float loadFactor){
        this(DEFAULT_INITIAL_CAPACITY , loadFactor , MAX_CAPACITY) ;
    }

    public SimpleHashMap(int initialCapacity , int maxCapacity){
        this(initialCapacity , DEFAULT_LOAD_FACTOR , maxCapacity) ;
    }

    public SimpleHashMap(int initialCapacity , float loadFactor , int maxCapacity){
        if(initialCapacity < 0){
            throw new IllegalArgumentException("initialCapacity is illegal data") ;
        }
        if (maxCapacity < initialCapacity || maxCapacity > MAX_CAPACITY){
            maxCapacity = MAX_CAPACITY ;
        }
        if (loadFactor <=0 || Float.isNaN(loadFactor)){
            throw new IllegalArgumentException("loadFactor is illegal data") ;
        }
        this.size = 0 ;
        this.threshold = twoPower(initialCapacity) ;
        this.maxCapacity = twoPower(maxCapacity) ;
        this.loadFactor = loadFactor ;
        this.modCount = 0 ;
    }


    //----------------------------Constructor Over---------------------------------


    //----------------------------Node---------------------------------
    static class Node<K,V> implements Map.Entry<K,V>{

        final int hash ;
        final K key ;
        V value ;
        Node<K,V> next ;

        public Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return this.key;
        }

        @Override
        public V getValue() {
            return this.value;
        }

        @Override
        public V setValue(V value) {
            V oldVal = this.value ;
            this.value = value ;
            return oldVal ;
        }

        @Override
        public boolean equals(Object o) {
            if (o == this){
                return true ;
            }
            if (o instanceof Map.Entry){
                Map.Entry<?,?> m  = (Map.Entry<?,?>)o ;
                if (Objects.equals(this.key , m.getKey()) &&
                    Objects.equals(this.value , m.getValue())){
                    return true ;
                }
            }
            return false;
        }

        /**
         * key的hash和value的hash做异或运算
         * @return
         */
        @Override
        public int hashCode() {
            return Objects.hashCode(this.key) ^ Objects.hashCode(this.value);
        }

        @Override
        public String toString() {
            return "Node{" +
                    "hash=" + hash +
                    ", key=" + key +
                    ", value=" + value +
                    ", next=" + next +
                    '}';
        }
    }

    //----------------------------Node Over---------------------------------

    /**
     * 找到大于cap的最小2的次幂数
     * @param size
     * @return
     */
    private static int twoPower(int size) {
        int n = DEFAULT_INITIAL_CAPACITY ;
        while(n < size){
            n = n << 1 ;
        }
        return n ;
    }

    private Node<K,V>[] resize(){

        Node<K,V>[] oldTable = this.table ;
        int oldCap = this.table == null ? 0 : this.table.length ;
        int oldThr = threshold ;

        int newCap = 0 ;
        int newThr = 0 ;

        //确定newCap、newThr
        if (oldCap > 0){
            //table已经最大了
            if (oldCap >= maxCapacity){
                this.threshold = maxCapacity ;
                return oldTable ;
            }
            else if ((newCap = oldCap << 1) <= maxCapacity){
                newThr = oldThr << 1 ;
            }
        } else{
            newCap = oldThr ;
            newThr = (int)(newCap*loadFactor) ;
        }
        
        if (newThr == 0){
            int t = (int)(newCap*this.loadFactor) ;
            newThr = t >= maxCapacity ? maxCapacity : t ;
        }
        
        //创建新的数组
        Node<K,V>[] newTable = (Node<K,V>[]) new Node[newCap] ;
        
        this.table = newTable ;
        this.threshold = newThr ;
        
        //如果oldTable不为空
        if (oldTable != null && oldTable.length != 0){
            //新数组和旧数组传递数据
            transfer(newTable , oldTable) ;
        }
        return this.table ;
    }

    /**
     * 新旧数组交接数据
     * @param newTable
     * @param oldTable
     * @return
     */
    private Node<K,V>[] transfer(Node<K,V>[] newTable, Node<K,V>[] oldTable) {
        Node<K,V>[] nT = newTable ;
        Node<K,V>[] oT = oldTable ;
        if (oT != null && nT != null && nT.length == (oT.length << 1)){
            int l = oT.length ;
            for (int i=0 ; i<l ; i++){
                Node<K,V> e ;
                if ((e = oT[i]) == null){
                    continue ;
                }
                
                if (e.next == null){
                    //单元素
                    nT[e.hash & (l-1)] = e ;
                }else{
                    //链表
                    //低位链表
                    Node<K,V> loHead = null , loTail = null ;
                    //高位链表
                    Node<K,V> hiHead = null , hiTail = null ;
                    //链表分离
                    Node<K,V> pre = e ;
                    while(pre != null){
                        if ((pre.hash&l) == 0){
                            if (loHead == null){
                                loHead = pre ;
                            }else{
                                loTail.next = pre ;
                            }
                            loTail = pre ;
                        }else{
                            if (hiHead == null){
                                hiHead = pre ;
                            }else{
                                hiTail.next = pre ;
                            }
                            hiTail = pre ;
                        }
                        pre = pre.next ;
                    }

                    if (loTail != null){
                        loTail.next = null ;
                        newTable[i] = loHead ;
                    }
                    if (hiTail != null){
                        hiTail.next = null ;
                        newTable[i+l] = hiHead ;
                    }
                }
            }
        }
        return newTable ;
    }


    @Override
    public int size() {
        return this.size ;
    }


    @Override
    public boolean isEmpty() {
        return this.size == 0;
    }

    @Override
    public boolean containsKey(Object key) {
        return getNode(hash(key) , key) != null ;
    }

    @Override
    public boolean containsValue(Object value) {
        Node<K,V>[] tab ;
        Node<K,V> e ;
        V v ;
        if (value == null || (tab = this.table) == null || tab.length == 0){
            return false ;
        }
        int l = this.table.length ;
        for (int i=0 ; i<l ; i++){
            e = tab[i] ;
            while(e != null){
                if ((v = e.value) == value || v.equals(value)){
                    return true ;
                }
                e = e.next ;
            }
        }
        return false ;
    }

    @Override
    public V get(Object key) {
        Node<K,V> e = getNode(hash(key) , key);
        return  e == null ? null : e.value ;
    }

    /**
     * 根据key获取Node
     * @param hash
     * @param key
     * @return
     */
    private Node<K,V> getNode(int hash, Object key) {

        if (hash == -1){
            return null ;
        }
        if (this.table == null || this.table.length == 0){
            return null ;
        }
        int l = this.table.length ;
        Node<K,V> e = this.table[hash & (l-1) ] ;
        Node<K,V> r = null ;
        while(e != null){
            if (e.hash == hash && (e.key == key || e.key.equals(key))){
                r = e ;
                break ;
            }
            e = e.next ;
        }
        return r ;
    }

    @Override
    public V put(K key, V value) {
        return putVal(hash(key) ,key , value);
    }

    /**
     * 计算hash,扰动函数,前16位和后16位作异或运算
     * @param key
     * @return
     */
    private int hash(Object key) {
        int h = key.hashCode() ;
        return key == null ? -1 : h ^ (h>>>16);
    }

    /**
     * 
     * @param hash
     * @param key
     * @param value
     * @return
     */
    private V putVal(int hash , K key, V value) {

        if (key == null || value == null){
            throw new NullArgumentException("key or value is null") ;
        }

        Node<K,V>[] tab;
        Node<K,V> p ;
        int n = 0 ;
        int i = 0 ;
        if ((tab = this.table) == null || (n = tab.length) == 0){
            //bug已修改
            n = (tab = resize()).length ;
        }
        //tab位置没有节点
        if ((p = tab[i = (hash & (n-1))]) == null){
            tab[i] =  newNode(hash , key , value , null)  ;
        }else {
            Node<K,V> e = null;
            K k = null ;
            //首节点
            if (p.hash == hash && (k = p.key) == key && k.equals(key)){
                e = p ;
            }
            //链表插入
            else if (p instanceof Node){
                for (int binCount = 1 ; ; binCount++){
                    if ((e = p.next) == null){
                        p.next = newNode(hash,key,value,null) ;
                        break ;
                    }
                    if (p.hash == hash && (k = p.key) == key && k.equals(key)){
                        break ;
                    }
                    p = e ;
                }
            }
            // 如果e是被替换掉的值 返回
            if (e != null){
                V oldValue = e.value ;
                e.value = value ;
                return oldValue ;
            }
        }
        addCount(1L , this.modCount) ;
        if (++size > threshold){
            resize() ;
        }
        return null ;
    }

    /**
     * 
     * @param l
     * @param modCount
     */
    private void addCount(long l, long modCount) {
        modCount += l ;
    }

    /**
     * 创建新的节点
     * @param hash
     * @param key
     * @param value
     * @param next
     * @return
     */
    private Node<K, V> newNode(int hash, K key, V value, Node<K,V> next) {
        return new Node<>(hash , key , value , next);
    }

    @Override
    public V remove(Object key) {
        Node<K,V> e = removeNode(hash(key) , key ) ;
        return e == null ? null : e.value ;
    }

    /**
     * 移除节点
     * @param hash
     * @param key
     * @return
     */
    private Node<K,V> removeNode(int hash, Object key ) {
        Node<K,V>[] tab ;
        int l ;
        if ((tab = this.table) != null && (l = tab.length) != 0){
            int i ;
            Node<K,V> e , p = null , node = null ;
            if ((e = tab[i = (hash & (l-1))]) == null){
                return null ;
            }
            if (e.hash == hash && (e.key == key || e.key.equals(key))){
                node = e ;
            }else{
                p = e ;
                while(p.next != null){
                    //System.out.println("{"+p.next.key+" "+key+" "+(p.next.key.equals(key))+" "+p.next.hash+" "+hash+" "+(p.next.hash == hash)+"}");
                    if (p.next.hash == hash && (p.next.key == key || p.next.key.equals(key))){
                        node = p.next ;
                        break ;
                    }
                    p = p.next ;
                }
            }

            if (node != null){
                if (e == node){
                    tab[i] = node.next ;
                }else{
                    p.next = node.next ;
                }
                --this.size ;
                addCount(1L ,this.modCount);
            }
            return node ;
        }
        return null ;
    }

    @Override
    public void putAll(Map<? extends K , ? extends V> m) {
        if (m == null || m.size() == 0){
            return ;
        }
        if (m.size() + this.size > maxCapacity){
            throw new IllegalArgumentException("map's size is very big to give rise to add unsuccessfully") ;
        }
        for (Map.Entry<? extends K , ? extends V> entry : m.entrySet()) {
            putVal(hash(entry.getKey()) , entry.getKey() , entry.getValue()) ;
        }
    }

    @Override
    public void clear() {
        int l ;
        Node<K,V>[] tab ;
        Node<K,V> e ;
        //帮助GC
        if ((tab = this.table) == null || (l = tab.length) == 0){
            return ;
        }
        for (int i=0 ; i<l ; i++){
            if ((e = tab[i]) == null){
                continue ;
            }else{
                tab[i] = null ;
                Node<K,V> next ;
                while(e != null){
                    next = e.next ;
                    e.next = null ;
                    e = next ;
                }
            }
        }
        this.size = 0 ;
        addCount(1L , this.modCount) ;
    }

    /**
     * 需要改进
     * @return
     */
    @Override
    public Set keySet() {
        Set<K> set = null ;
        Node<K,V>[] tab ;
        Node<K,V> e ;
        int l ;
        if ((tab = this.table) == null || (l = tab.length) == 0){
            return set ;
        }
        set = new HashSet<>() ;

        for (int i=0 ; i<l ; i++){
            e = tab[i] ;
            while(e != null){
                set.add(e.key) ;
                e = e.next ;
            }
        }
        return set ;
    }


    @Override
    public Collection<V> values() {
        Collection<V> collection = null ;
        Node<K,V>[] tab ;
        Node<K,V> e ;
        int l ;
        if ((tab = this.table) == null || (l = tab.length) == 0){
            return collection ;
        }
        collection = new ArrayList<>() ;
        for (int i=0 ; i<l ; i++){
            e = tab[i] ;
            while(e != null){
                collection.add(e.value) ;
                e = e.next ;
            }
        }
        return collection ;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        Set<Map.Entry<K,V>> set = null ;
        Node<K,V>[] tab ;
        Node<K,V> e ;
        int l ;

        if ((tab = this.table) == null || (l = tab.length) == 0){
            return set ;
        }
        set = new HashSet<>() ;
        for (int i=0 ; i<l ; i++){
            e = tab[i] ;
            while(e != null){
                set.add(e) ;
                e = e.next ;
            }
        }
        return set ;
    }

    /**
     * 数据量过大可能会崩溃
     * @return
     */
//    public String toString() {
//        Node<K,V> e ;
//        Node<K,V>[] tab = this.table ;
//        int l = tab.length ;
//        StringBuilder result = new StringBuilder();
//        for (int i=0 ; i<l ; i++){
//            if ((e = tab[i]) != null){
//                while(e != null){
//                    result.append(e.toString()+"\n") ;
//                    e = e.next ;
//                }
//                result.append("---------table["+i+"]结束-----------"+"\n");
//            }
//        }
//        return result.toString() ;
//    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值