zoukankan      html  css  js  c++  java
  • HashMap原理及简单实现

    public class MyHashMap<K, V> {
    	private class Entry<K, V> {
    		int hash;
    		K key;
    		V value;
    		Entry<K, V> next;
    
    		Entry(int hash, K key, V value, Entry<K, V> next) {
    			this.hash = hash;
    			this.key = key;
    			this.value = value;
    			this.next = next;
    		}
    	}
    
    	private static final int DEFAULT_CAPACITY = 1 << 2;
    
    	private Entry<K, V>[] table;
    
    	private int capacity;
    
    	private int size;
    
    	private final float loadFactor = 0.75f;
    
    	public MyHashMap() {
    		this(DEFAULT_CAPACITY);
    	}
    
    	@SuppressWarnings("unchecked")
    	public MyHashMap(int capacity) {
    		if (capacity < 0) {
    			throw new IllegalArgumentException();
    		} else {
    			table = new Entry[capacity];
    			size = 0;
    			this.capacity = capacity;
    		}
    	}
    
    	public int size() {
    		return size;
    	}
    
    	public boolean isEmpty() {
    		return size == 0 ? true : false;
    	}
    
    	public V put(K key, V value) {
    		if (key == null) {
    			throw new RuntimeException("key不可以为空!");
    		}
    		if (size >= capacity * loadFactor) {
    			// 开始rehash
    			resize(2 * table.length);
    			int hash = (null != key) ? hash(key) : 0;
    			int index = indexFor(hash, table.length);// 注意此时的table已经扩容了
    		}
    		V newValue = putEntry(key, value);
    		return newValue;
    	}
    
    	@SuppressWarnings({ "rawtypes", "unchecked" })
    	private void resize(int newCapacity) {
    		System.out.println("我们要扩容了!!当前的size是:" + size);
    		// 让数组长度乘以两倍
    		Entry[] newTable = new Entry[newCapacity];
    		transfer(newTable, true);
    		table = newTable;
    	}
    
    	@SuppressWarnings({ "rawtypes", "unchecked" })
    	private void transfer(Entry[] newTable, boolean rehash) {
    		int newCapacity = newTable.length;
    		for (Entry<K, V> e : table) {
    			while (e != null) {
    				if (rehash) {
    					// 要重新hash
    					e.hash = null == e.key ? 0 : hash(e.key);
    				}
    				int index = indexFor(e.hash, newCapacity);
    				// 开始把e放进新的数组中
    				// 注意,每次插入新的值都必须要插在散列链表的头部
    				e.next = newTable[index];
    				newTable[index] = e;
    				e = e.next;
    			}
    		}
    	}
    
    	private V putEntry(K key, V value) {
    		if (key == null) {
    			throw new RuntimeException("key不可以为空!");
    		}
    		int hash = hash(key);
    		int i = indexFor(hash, table.length);
    		Entry<K, V> newEn = new Entry<K, V>(hash, key, value, null);
    		for (Entry<K, V> e = table[i]; e != null; e = e.next) {
    			Object k;
    			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    				// 代表当前的e和要添加的key冲突了,那么就覆盖
    				V oldValue = e.value;
    				e.value = value;// 当前的e的value要替换为新的value
    				return oldValue;
    			}
    		}
    		// 如果上面没有找到的话,就要往链表添加元素了
    		size++;
    		addEntry(newEn, i);
    		return value;
    	}
    
    	private void addEntry(Entry<K, V> entry, int index) {
    		Entry<K, V> e = table[index];
    		table[index] = entry;
    		entry.next = e;
    	}
    
    	public V get(K key) {
    		if (key == null) {
    			throw new RuntimeException("key不可以为空!");
    		}
    		Entry<K, V> entry = getEntry(key);
    		return null == entry ? null : entry.value;
    	}
    
    	private Entry<K, V> getEntry(K key) {
    		if (size == 0) {
    			return null;
    		}
    		int hash = (key == null) ? 0 : hash(key);
    		int i = indexFor(hash, table.length);
    		for (Entry<K, V> e = table[i]; e != null; e = e.next) {
    			Object k;
    			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    				return e;
    			}
    		}
    		return null;
    	}
    
    	public V remove(K key) {
    		Entry<K, V> e = removeEntryForKey(key);
    		return (e == null ? null : e.value);
    	}
    
    	private Entry<K, V> removeEntryForKey(K key) {
    		if (size == 0) {
    			return null;
    		}
    		int hash = (key == null) ? 0 : hash(key);
    		int i = indexFor(hash, table.length);
    		Entry<K, V> cur = table[i];
    		Entry<K, V> e = cur;
    		while (e != null) {
    			if (e.hash == hash && (e.key == key || key.equals(e.key))) {
    				size--;
    				// 如果删除的是prev的话
    				if (cur == e) {
    					table[i] = e.next;
    				} else {
    					// 就让cur的next等于e的next
    					cur.next = e.next;
    				}
    				return e;
    			}
    			cur = e;
    			e = e.next;
    		}
    		return null;
    	}
    
    	private int indexFor(int hash, int length) {
    		return hash & (length - 1);// 哈希值和长度减一做与运算
    	}
    
    	private int hash(K key) {
    		return key.hashCode();
    	}
    
    	public static void main(String[] args) {
    		MyHashMap<Integer, String> map = new MyHashMap<>();
    	}
    }
    

      

  • 相关阅读:
    Java读书笔记
    b_aw_旅游计划(树的中心变形)
    b_lc_秋叶收集器(分类讨论dp+滚动数组优化)
    b_lg_涂色(从小区间做起,讨论s[l]和s[r]的关系)
    c_lc_早餐组合(排序+双指针)
    c_aw_鱼塘钓鱼(大根堆)
    b_pat_栈(2*multiset+stack)
    c_pat_推荐系统(set模拟)
    b_lg_时态同步(后序遍历统计每棵子树的最大高度)
    b_lc_统计不开心的朋友(预处理+模拟)
  • 原文地址:https://www.cnblogs.com/Booker808-java/p/8906501.html
Copyright © 2011-2022 走看看