源码——手写一个简单的HashMap

定义:用于存储Key-Value键值对集合,

存储结构:线性链表(数组+链表)。数组:固定长度,索引效率高,增删效率低-----链表:长度不固定,索引效率低,增删效率高

散列值特点:同一对象调用多次hashcode()方法,必须返回相同的数值。(幂等)

                    如果两个对象根据equals()方法比较是相等的,那么两个对象调用hashcode()方法返回的结果必须相等;

                                if(a==b)   a.hashcode()==b.hashcode()

                    如果两个对象的equals()方法比较是不相等的,那么两个对象调用hashcode()方法返回的结果不一定不相等

hash算法实现:取模,求与,线性探测,其他 

 

public interface Map<K,V> {

	//向hashMap中插入值
	public V put(K k,V v); 
	
	//根据key获取hashMap中的值
	public V get(K k);
	
	//获得集合中元素的个数
	public int size();
	
	//获取集合中,键值对的对象
	interface Entry<K,V>{
		K getKey();
		
		V getValue();
		
		V setValue(V v);
		
	}
}

 

package HashMap;


public class HashMap<K, V> implements Map<K, V> {
	//数据存储的结构==>数组+链表
	Node<K,V>[] array=null;
	
	//数组/哈希桶的长度 
	private static int defaultLength=16;
	
	//加载因子/扩容因子
	private static double factor=0.75D;
	
	//集合中的元素个数
	private int size;

	//测试打印函数
	public void print() {
		System.out.println("===============================");
		if(array!=null) {
			Node<K, V> node=null;			
			for (int i = 0; i < array.length; i++) {
				node=array[i];
				System.out.print("下标["+i+"]");
				//遍历链表
				while(node!=null) {
					System.out.print("["+node.getKey()+":"+node.getValue()+"]");
					if(node.next!=null) {
						node=node.next;
					}else {
						//到尾部元素
						node=null;
					}
				}
				System.out.println();
			}
			
		}
	}
	
	//put元素方法
	@Override
	public V put(K k, V v) {
		
		//1.懒加载机制,使用的时候进行分配
		if(array==null) {
			array=new Node[defaultLength];
		}
		
		//2.通过hash算法,计算出具体插入的位置
		int index=position(k,defaultLength);
		
		
		//扩容。判断是否需要扩容
		//扩容的准则,元素的个数   大于  桶的尺寸*加载因子
		if(size > defaultLength*factor) {
			resize();
		}
		
		//3.放入要插入的元素
		Node<K, V> node=array[index];
		if(node==null) {
			array[index]=new Node<K,V>(k,v,null);
			size++;
		}else {
			if(k.equals(node.getKey()) || k==node.getKey()) {
				return node.setValue(v);
			}else {
				array[index]=new Node<K,V>(k,v,node);
				size++;
			}
		}
			
		return null;
	}

	//扩容,并且重新排列元素
	private void resize() {
		//翻倍扩容
		//1.创建新的array临时变量,相当于defaultlength*2
		Node<K, V>[] temp=new Node[defaultLength << 1];
		
		//2.重新计算散列值,插入到新的array中去。 code=key % defaultLength ==> code=key % defaultLength*2
		Node<K, V> node=null;
		for (int i = 0; i < array.length; i++) {
			node=array[i];
			while(node!=null) {
				//重新散列
				int index=position(node.getKey(),temp.length);
				//插入头部
				Node<K, V> next = node.next;
				//3
				node.next=temp[index];
				//1
				temp[index]=node;
				//2
				node=next;
				
			}
		}
		
		//3.替换掉老array
		array=temp;
		defaultLength=temp.length;
		temp=null;
		
		
	}

	private int position(K k,int length) {
		int code=k.hashCode();
		
		//取模算法
		return code % (length-1);
		
		//求与算法
		//return code & (defaultLength-1);
	}

	@Override
	public V get(K k) {
		if(array!=null) {
			int index=position(k,defaultLength);
			Node<K, V> node=array[index];	
			//遍历链表
			while(node!=null) {
					//如果key值相同返回value
					if(node.getKey()==k) 					
						return node.getValue();
					else
						//如果key值不同则调到下一个元素
						node=node.next;
					}
				}
			
		
		return null;
	}

	@Override
	public int size() {
		 
		return size;
	}

	static class Node<K,V> implements Entry<K,V>{
		K key;
		V value;
		Node<K,V> next;
		
		
		public Node(K key, V value, Node<K, V> next) {
			super();
			this.key = key;
			this.value = value;
			this.next = next;
		}

		@Override
		public K getKey() {
			return this.key;
		}

		@Override
		public V getValue() {
			return this.value;
		}

		@Override
		public V setValue(V v) {
			V oldValue=this.value;
			this.value=v;
			return oldValue;
		}
		
	}
}
public class Test {
	public static void main(String[] args) {
		HashMap<String, String> map=new HashMap<String, String>();
		map.put("001号", "001");
		map.put("002号", "002");
		map.put("003号", "003");
		map.put("004号", "004");
		map.put("005号", "005");
		map.put("006号", "006");
		map.put("007号", "007");
		map.put("008号", "008");
		map.put("009号", "009");
		map.put("010号", "010");
		map.put("011号", "011");
		map.print();
		
		System.out.println("========>"+map.get("009号"));
	}
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值