• Java SE HashMap的底层实现


    1.hash散列算法

      由于hashmap在存储过程中是数组加链表的存储过程,所以定义数组长度为16(建议是2的n次幂的长度),之后进行每个数组的地址都指向一个链表进行存储

      hash表算法可对数组长度length取余,如果length是2的n次幂,则可对length-1取位运算&

      例如,任意长度8是2的3次幂,随机的int值对8取余,和对7进行&运算得到的结果是一样的

    int a=33565366;
    System.out.println(a%8);
    System.out.println(a&7);

      在jdk 7之前的源码中,则对hash凑得进行了2次散列处理,为了使散列更均匀

      在jdk 8往后,数组长度大于8时,链表转换为红黑树,大大提高了查找速率

      

    2.手工实现hashMap

      取数据

        1.首先通过key计算hashcode来得到数组的存储,再通过next便利链表进行查找比较,直到返回true的节点对象为止

        2.Java中有规定,两个内容相同的(调用equals方法值为true的)对象必须有想等的hashcode,如果两个对象内容相等,而hashcode的值不一样,则会产生悖论

      扩容问题

        1.jdk7之前

        hashMap的位桶数组,初始大小为16,实际使用时,大小可变,如果位桶数组中元素个数达到(0.75*数组length),就重新调整数组为2倍大小,扩容是个耗时的过程,相当于重新定义数组和链表,进行复制操作

        2.jdk8之后

        位桶数组初始大小为16,当链表长度大于8时,将链表中各个元素拷贝到红黑树上,大大提高了查找效率

    3.源代码

      

    package com.littlepage.HashMap;
    /**
     * 用于LittlePagesHashMap的Node
     * @author LittlePage
     */
    public class Node<K,V> {
        private int hash;
        private K key;
        private V value;
        private Node<K,V> next;
        
        public Node(K key, V value) {
            super();
            this.key = key;
            this.value = value;
        }
    
        public int getHash() {
            return hash;
        }
    
        public void setHash(int hash) {
            this.hash = hash;
        }
    
        public K getKey() {
            return key;
        }
    
        public void setKey(K key) {
            this.key = key;
        }
    
        public V getValue() {
            return value;
        }
    
        public void setValue(V value) {
            this.value = value;
        }
    
        public Node<K, V> getNext() {
            return next;
        }
    
        public void setNext(Node<K, V> next) {
            this.next = next;
        }
    
        @Override
        public String toString() {
            return "(" + key + "," + value + ")";
        }
        
        
        
        
    }
    package com.littlepage.HashMap;
    
    public class LittlePagesHashMap<K,V> {
        
        
        Object[] table=new Node[16];       //位桶数组
        
        int size;//存放键值对个数
        
        
        public LittlePagesHashMap(){
            table=new Node[16];
        }
        
        public void put(K key,V value){
            //定义了新的节点对象
            Node<K,V> newNode=new Node<>(key,value);
            newNode.setHash(myHash(key.hashCode(), table.length));
            
            @SuppressWarnings("unchecked")
            Node<K,V> temp=(Node<K, V>) table[newNode.getHash()];
            if(temp==null){
                table[newNode.getHash()]=newNode;
            }else{
                while(temp.getNext()!=null){
                    if(temp.getKey().equals(newNode.getKey())){
                        temp.setValue(newNode.getValue());
                        size++;
                        return;
                    }
                    temp=temp.getNext(); 
                }
                temp.setNext(newNode);
            }
            size++;
        }
        
        public int myHash(int hashcode,int length){
            return hashcode&(length-1);
        }
        
        @Override
        public String toString(){
            StringBuilder sb=new StringBuilder();
            sb.append("[");
            for(int i=0;i<table.length;i++){
                if(table[i]==null) continue;
                else{
                    @SuppressWarnings("unchecked")
                    Node<K,V> temp=(Node<K, V>) table[i];
                    sb.append(temp);
                    while((temp=temp.getNext())!=null){
                        sb.append(","+temp);
                    }
                    sb.append("]");
                }
            }
            return sb.toString();
        }
    }
    package com.littlepage.HashMap;
    
    public class Test {
        public static void main(String[] args) {
            LittlePagesHashMap<String, String> a=new LittlePagesHashMap<>();
            a.put("a", "gg");
            a.put("12", "pp");
            System.out.println(a);
        }
    }
  • 相关阅读:
    苏教版国标本小学语文第一册汉字笔画
    C++ preprocessor __VA_ARGS__ number of arguments
    The Aggregate Magic Algorithms
    USB Mass Storage大容量存储的基本知识
    【转】驱动和应用层的三种通信方式
    Do You Actually Know What *P++ Does In C?
    Repeat Macro Cloak
    A SCSI command code quick reference
    USB device layout, descriptors, interface alternate setting
    RTOS Semaphore Services
  • 原文地址:https://www.cnblogs.com/littlepage/p/10335170.html
Copyright © 2020-2023  润新知