HashMap

(非红黑数结构)盗版的HashMap--------------------get,put两个方法

底层使用的是数组+单链表

数组:存储空间连续,比较占内存,寻址容易,插入删除复杂

链表:存储空间非连续,占用内存松散,寻址困难,插入删除容易

HashMap

HashMap

import java.util.AbstractMap;
import java.util.Arrays;

public class MHashMap<K,V>{
	
	//需要一个类似Entry的类 用来存储 KEY VALUE 以及下个对象
	private class MEntry{
		
		private K KEY;
		private V VALUE;
		private MEntry next;

		public MEntry() {
		}
		public MEntry(K kEY, V vALUE, MHashMap<K, V>.MEntry next) {
			super();
			KEY = kEY;
			VALUE = vALUE;
			this.next = next;
		}
		public K getKEY() {
			return KEY;
		}
		public void setKEY(K kEY) {
			KEY = kEY;
		}
		public V getVALUE() {
			return VALUE;
		}
		public void setVALUE(V vALUE) {
			VALUE = vALUE;
		}
		public MEntry getNext() {
			return next;
		}
		public void setNext(MEntry next) {
			this.next = next;
		}
		@Override
		public String toString() {
			return "MEntry [KEY=" + KEY + ", VALUE=" + VALUE + ", next=" + next + "]";
		}
	}
	
	//初始化操作
	//1.默认数组的大小
	private static final int INIT_CAPATITY=1<<4;
	//2.加载因子
	private static final float INIT_LOADFACTOR=0.75f;
	//3.临界值 就是数组元素个数在多少的时候进行扩容
	private Object[] object = new Object[INIT_CAPATITY];
	//4.容量的值
	private int addCapatity=INIT_CAPATITY;
	//5.设置hashMap的最大值
	//private static final int MAX_PACATITY=65535;
	
	//根据key 获取hashcode
	public int getHashCode(K key) {
		System.out.println("哈希值:"+(key.hashCode()&(addCapatity-1)));
		return key.hashCode()&(addCapatity-1);
	}
	
	//put函数  首先要检查 是否满足扩容
	public void put(K key,V value) {
		//将key和value保存到 这个数组中		 
		MEntry mEntry = new MEntry(key,value,null);
		//计算此时已经存储的个数
		int sum = 0;
		for(int i=0;i<addCapatity;i++) {			
			if(object[i]!=null) {
	     		//遍历 链表 头指针是当前对象 
				@SuppressWarnings("unchecked")
				MEntry head = (MHashMap<K, V>.MEntry) object[i];
				MEntry p = head;
				sum++;
				while(p.next!=null) {
					sum++;
					p = p.next;
				}	
			}
		}

		//如果sum这个值大于等于 临界值 的话  那么就进行扩容  扩为原来的2倍
		if(sum>=addCapatity*INIT_LOADFACTOR) {
			addCapatity = addCapatity*2;
			object = Arrays.copyOf(object, addCapatity);
		}
		//扩容完成 计算哈希值 
		int hashCode = getHashCode(key);
		// 检查该位置的中是否有元素  如果没有元素  那么直接存入数组中
		if(object[hashCode]!=null) {
			//如果有元素
			@SuppressWarnings("unchecked")
			//根据哈希值 找到这个位置的所有元素
			MEntry head = (MHashMap<K, V>.MEntry) object[hashCode];
			MEntry p = head;
			boolean flag = false;
			//遍历所有 这个位置的所有元素
			while(p.next!=null) {
				//如果这个键存在 那么就覆盖这边value 
				if(p.getKEY() == mEntry.getKEY()) {
					//覆盖
					flag = true;
					p.setVALUE(mEntry.getVALUE());
				
					break;
				}
				p = p.next;
			}
			//如果 不存在这样的键 那么直接插入尾巴节点
			if(!flag) {
				p.next = mEntry;
			}
				
		}else {
			//如果是空的 那么就直接存入
			object[hashCode] = mEntry;
			
		}	
	}
	
	public V get(K key) {
		//通过KEY 来进行索引
		@SuppressWarnings("unchecked")
		//根据哈希值 计算出 这个键的哈希值 对应的 所有元素
		MEntry mEntry = (MHashMap<K, V>.MEntry) object[getHashCode(key)];
		//如果头节点是null   就说明不存在  直接返回空  否则的话  就说明 这个数组的头节点 是有值的  那么看一下这个的next域是
		//不是空的 如果是的话就是这个值 直接返回就行 否则就遍历寻找
		System.out.println(mEntry);
		if(mEntry!=null) {
			MEntry head = mEntry;
			MEntry p = head;
			if(p.next!=null) {
				while(p!=null) {
					if(key.equals(p.getKEY())) {
						return p.getVALUE();
					}
					p = p.next;
					}
			}else {
				return p.VALUE;
			}
		}
		return null;
	}
}

结果测试:

		Map<String,String> map = new HashMap<String, String>();
		for (int i=0;i<18;i++) {
			map.put("name"+i, "ZhangSan"+i);
			map.hashCode();
		}
		System.out.println("正版MAP:"+map.get("name3"));
		
		MHashMap<String, String> mHashMap = new MHashMap<String,String>();
		for (int i=0;i<18;i++) {
			mHashMap.put("name"+i, "ZhangSan"+i);
		}
		System.out.println("盗版MAP:"+mHashMap.get("name5"));

HashMap