zoukankan      html  css  js  c++  java
  • Java

     HashMap的位桶数组实际使用时,大小是可变的。如果位桶数组中的元素达到(0.75*数组 length), 就重新调整数组大小变为原来2倍大小。

    未扩容时的代码如下:

    /**
     * 新建一个节点
     * put方法增加键值对,键相同时覆盖相应节点,不同时放在最后
     * 在table同一个地址的next增加值
     * 重写toString方法
     * get的方法
     */
    
    package mypro09;
    
    public class SxtHashMap03 {
        Node2[] table; //位桶数组。bucket array
        int size; //存放键值对的个数
        
        public SxtHashMap03(){
            table = new Node2[16]; //长度一般定义为2的整数幂
        }
        
        public Object get(Object key) {
            
            int hash = myHash(key.hashCode(), table.length);
            Object value = null;
            
            if(table[hash]!=null) {
                Node2 temp = table[hash];
                
                while(temp!=null) {
                    if(temp.key.equals(key)) { //如果相等,则说明了找到键值对,返回相应的value
                        value = temp.value;
                        break;
                    }else {
                        temp = temp.next;
                    }
                }
            }
            
            return value;
        }
        
        public void put(Object key, Object value) {
            
            //如果要完善。还需要考虑数组扩容问题!!!见ArrayList!!!!
            
            
            //定义了新的节点对象
            Node2 newNode = new Node2();
            newNode.hash = myHash(key.hashCode(), table.length);
            newNode.key = key;
            newNode.value = value;
            newNode.next = null;
            
            Node2 temp = table[newNode.hash];
            
            Node2 iterLast = null; //正在遍历的最后一个元素,为保存遍历的最后一个节点信息
            boolean keyRepeat = false; //在循环外判断循环到最后一个也没有找到重复key的情况
            if(temp==null) {
                //此处数组元素为空,则直接将新节点放进去
                table[newNode.hash] = newNode;
            }else {
                //此处数组元素不为空,遍历对应链表
                while(temp!=null) {
                    
                    //判断key如果重复,则覆盖
                    if(temp.key.equals(key)) {
                        keyRepeat = true;
                        temp.value = value; 
                        break;
                    }else {
                        //如果key不重复,则遍历下一个
                        iterLast = temp;
                        temp = temp.next;
                    }
                }
                if(!keyRepeat) { //没有发生key重复的情况,则添加到链表最后
                    iterLast.next = newNode;
                }
            }
        }
        
        @Override
        public String toString() {
            //[10:aa, 20:bb]
            StringBuilder sb = new StringBuilder("[");
            
            //遍历bucket数组
            for(int i=0;i<table.length;i++) {
                Node2 temp = table[i];
                
                //遍历链表
                while(temp!=null) {
                    sb.append(temp.key+":"+temp.value+",");
                    temp = temp.next;
                }
            }
            sb.setCharAt(sb.length()-1, ']');
            return sb.toString();
        }
        
        //用v=key.hashCode,求出哈希值
        public static int myHash(int v, int length) {
    //        System.out.println("hash in myHash" + (v&(length-1))); //直接位运算,效率较高
    //        System.out.println("hash in myHash" + (v%(length))); //直接取模运算,效率较低
            return v&(length-1);
        }
        
        public static void main(String[] args) {
            SxtHashMap03 map = new SxtHashMap03();
            map.put(10, "aa");
            map.put(20, "bb");
            map.put(30, "cc");
            map.put(30, "22c");
            
            map.put(53, "gg");
            map.put(69, "ff");
            map.put(85, "shua");
            
            System.out.println(map);
            
            System.out.println(map.get(53));
    //        for(int i=10;i<100;i++) {
    //            System.out.println(i+"---"+myHash(i, 16)); //53,69,85
    //        }
            
        }
    }

    对put函数增加扩容功能,为方便验证算法正确此处将table的length改为了4

    修改后如下:

        int tNodeCount = 0; //存放位桶数组元素个数
        public void put(Object key, Object value) {
            
            //如果要完善。还需要考虑数组扩容问题!!!见ArrayList!!!!
            
            
            //定义了新的节点对象
            Node2 newNode = new Node2();
            newNode.hash = myHash(key.hashCode(), table.length);
            newNode.key = key;
            newNode.value = value;
            newNode.next = null;
            
            Node2 temp = table[newNode.hash];
            
            Node2 iterLast = null; //正在遍历的最后一个元素,为保存遍历的最后一个节点信息
            boolean keyRepeat = false; //在循环外判断循环到最后一个也没有找到重复key的情况
            
            
            if(temp==null) {
                //此处数组元素为空,则直接将新节点放进去
                tNodeCount++;
                table[newNode.hash] = newNode;
                //什么时候扩容
                if(tNodeCount==0.75*table.length) {
                    
                    //怎么扩容,如果位桶数组中的元素达到(0.75*数组 length),就重新调整数组大小变为原来2倍大小。
                    Node2[] newTable = new Node2[table.length<<1]; //4-->4*2
                    System.arraycopy(table, 0, newTable, 0, table.length);
                    table = newTable;
                }
                
            }else {
                //此处数组元素不为空,遍历对应链表
                while(temp!=null) {
                    
                    //判断key如果重复,则覆盖
                    if(temp.key.equals(key)) {
                        keyRepeat = true;
                        temp.value = value; 
                        break;
                    }else {
                        //如果key不重复,则遍历下一个
                        iterLast = temp;
                        temp = temp.next;
                    }
                }
                if(!keyRepeat) { //没有发生key重复的情况,则添加到链表最后
                    iterLast.next = newNode;
                }
                
            }
        }
        

    利用断点,可以看到原本table.length = 4,现在改为了table.length = 8

  • 相关阅读:
    字符串处理(包括正则生成工具)
    php.ini 个别字段笔记
    php-5.4 升级到 php7.2
    【mysql笔记】针对 group_concat 长度限制
    七牛,前端上传图片
    PHP 替换 特殊空白符
    【代码块】定时任务<swoole> 100%无人值守
    安装nodejs
    linux安装beanstalkd
    个人笔记上传 -- redis安装
  • 原文地址:https://www.cnblogs.com/kl-1998/p/10804609.html
Copyright © 2011-2022 走看看