zoukankan      html  css  js  c++  java
  • HashTable

    本文主要记录阅读HashTable源码的过程。

    1、类图结构

    2、内部子类

    子类 作用
    KeySet 集合,存放HashTable中所有的key
    Entry HashTable的元素,以链表的形式存放在HashTable的每一个index处
    EntrySet 集合,存放所有的Entry节点
    Enumerator  
    ValueCollection  

     2、初始化

    Hashtable的默认大小是11,平衡因子是0.75

    3、主要操作

    需要注意的是,HashTable类中的方法前面都有synchronized关键字,表明HashTable是可同步的

    put:添加元素

    public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();//计算hash值
            int index = (hash & 0x7FFFFFFF) % tab.length;//计算对应的index
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {//变量该index对应的“桶”是否已经存在相同的key,如果存在则用value替换原来的value
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);//向table中添加元素
            return null;
        }
    	
    private void addEntry(int hash, K key, V value, int index) {
    	modCount++;//结构修改次数+1
    
    	Entry<?,?> tab[] = table;
    	if (count >= threshold) {//如果超过阈值,则重新扩容
    		// Rehash the table if the threshold is exceeded
    		rehash();
    
    		tab = table;
    		hash = key.hashCode();//扩容后重新计算index
    		index = (hash & 0x7FFFFFFF) % tab.length;
    	}
    
    	// Creates the new entry.
    	@SuppressWarnings("unchecked")
    	Entry<K,V> e = (Entry<K,V>) tab[index];
    	tab[index] = new Entry<>(hash, key, value, e);
    	count++;
    }
    //扩容
    protected void rehash() {
    	int oldCapacity = table.length;
    	Entry<?,?>[] oldMap = table;
    
    	// overflow-conscious code
    	int newCapacity = (oldCapacity << 1) + 1; //capacity翻倍
    	if (newCapacity - MAX_ARRAY_SIZE > 0) {
    		if (oldCapacity == MAX_ARRAY_SIZE)
    			// Keep running with MAX_ARRAY_SIZE buckets
    			return;
    		newCapacity = MAX_ARRAY_SIZE;
    	}
    	Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
    
    	modCount++;
    	threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    	table = newMap;
    
    	for (int i = oldCapacity ; i-- > 0 ;) {//变量原有table中每一个桶
    		for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {//遍历桶中每一个元素,重新通过hash值计算index
    			Entry<K,V> e = old;
    			old = old.next;
    
    			int index = (e.hash & 0x7FFFFFFF) % newCapacity;
    			e.next = (Entry<K,V>)newMap[index];
    			newMap[index] = e;
    		}
    	}
    }
    

     

    remove

    //删除元素
    public synchronized V remove(Object key) {
    	Entry<?,?> tab[] = table;
    	int hash = key.hashCode();
    	int index = (hash & 0x7FFFFFFF) % tab.length;
    	@SuppressWarnings("unchecked")
    	Entry<K,V> e = (Entry<K,V>)tab[index];//获取桶中链表头
    	for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {//下面的算法就是单链表删除元素的算法
    		if ((e.hash == hash) && e.key.equals(key)) {
    			modCount++;
    			if (prev != null) {
    				prev.next = e.next;
    			} else {
    				tab[index] = e.next;
    			}
    			count--;
    			V oldValue = e.value;
    			e.value = null;
    			return oldValue;
    		}
    	}
    	return null;
    }
    

      

  • 相关阅读:
    iframe自适应高度的多种方法
    jquery 限制上传文件的类型和大小
    20200303 pandas
    20200306 Linux基础
    20200305 VMware虚拟机安装及centOS
    20200310 CMDB基础设计
    20200407 算法与数据结构
    20200403 MongoDB操作以及pyMongo
    20200402 MongoDB安装及简介
    20200401 docker部署与mysql主从搭建django读写分离
  • 原文地址:https://www.cnblogs.com/LCCRNblog/p/8366585.html
Copyright © 2011-2022 走看看