手写实现HashMap1.7版本

Map接口

public interface MyMap {
public V put(K k,V v);
public V get(K k);

/**
* 内部类
* @author mama
*
* @param
* @param
*/
public interface Entry{
public K getKey();
public V getValue();
}
}


HashMap的结构

 

定义的成员变量:

1、定义默认数组的大小  1<<4

private static int defaultLenth=1<<4;

2、定义有限的数组长度空间位置内会形成链表 0.75

private static double defaultAddSizeFactor=0.75;

3、定义数组的位置

private int useSize;

4、定义一个Entry table;

private Entry[]table=null;

 

有一个内部类,定义了Entry

class Entry<K,V>implements MyMap.Entry{

   

K k;

V v;

//指向被this挤压下去的Entry对象

Entry next;

public Entry(Kk,V v,Entry next) {

this.k=k;

this.v=v;

this.next=next;

}

@Override

public K getKey() {

// TODO Auto-generated method stub

return k;

}

 

@Override

public V getValue() {

// TODO Auto-generated method stub

return v;

}

}

 

定义构造类

1、无参的构造

public MyHashMap() {

this(defaultLenth,defaultAddSizeFactor);

}

2、有参的构造,传入数组的大小和元素占数组总容量形成链表的阈值0.75

public MyHashMap(int length,double defaultAddSizeFactor) {

if(length<0) {

throw new IllegalArgumentException("参数不能为负数"+length);

}

if(defaultAddSizeFactor<=0 || Double.isNaN(defaultAddSizeFactor)) {

throw new IllegalArgumentException("扩容标准必须是大于0的数字"+defaultAddSizeFactor);

}

this.defaultLenth=length;

this.defaultAddSizeFactor=defaultAddSizeFactor;

table=new Entry[defaultLenth];

}

 

 

定义put方法

//1、判断是否需要扩容

if(useSize>defaultLenth*defaultAddSizeFactor) {

//进行两倍的扩容

up2Size();

}

//如果这时扩容了,新数组扩容为2倍,老数组的数据被重新散列到新数组中

int index=getIndex(k,table.length);//得到了下标

Entry entry=table[index];

//table[index]的entry为空,说明没有相同的元素,也就形成不了链表

if(entry==null) {

table[index] =new Entry(k,v,null);

useSize++;//使用位置被占用+1

}else if(entry!=null) {//说明说相同的值,挤压下去,形成链表

table[index] =new Entry(k,v,entry);

}

return table[index].getValue();

}

 

1、判断是否需要扩容

if(useSize>defaultLenth*defaultAddSizeFactor) {

//进行两倍的扩容

up2Size();

}

1.1、扩容的方法

private void up2Size() {

Entry[] newTable=new Entry[2*defaultLenth];

//将老数组存的内容放到新数组,拿之前散列算法

//3.

againHash(newTable);

}

1.2、把老数组存到新数组的key值进行散列算法,在这之前把value存到list

private void againHash(MyHashMap.Entry[]newTable) {

List> entryList=new ArrayList.Entry>();

//找老数组中的对象

for (int i = 0;i < table.length;i++) {

//老数组没有数据

if(table[i]==null) {

continue;

}

//这个方法存找到不为空的对象存入entryList

foundEntryByNext(table[i],entryList);

}

//进行散列

if(entryList.size()>0) {

useSize=0;

defaultLenth=2*defaultLenth;

table=newTable;

for (Entryentry : entryList) {

//说明遍历的EntryList是链表,取消链表结构,把指定的下一个entry。next为null

if(entry.next!=null) {

entry.next=null;//为什么要致为null,因为foundEntryByNext()递归,把数据存到了list中变成了链表,next就不用再指向下一个值了

}

//没有形成链表,调用put

put(entry.getKey(),entry.getValue());

}

}

}

 

1.3、把不为空的对象存到list---使用递归

private void foundEntryByNext(MyHashMap.Entryentry, List.Entry>entryList) {

 if(entry!=null&&entry.next!=null) {

 entryList.add(entry);

 //递归

 foundEntryByNext(entry.next,entryList);

 }else {

 entryList.add(entry);//链表中只有一个

}

}

 

2、通过k和数组的长度范围,获取元素在数组中的位置的方法

private int getIndex(Kk, int length) {

//length 2^n 0000 1111

int m=length-1;

//保证index=【0,length)之间

int index=hash(k.hashCode()&m);//得到数组的位置(进行位运算)

return index;

}

 

2.1、按jdk1.7源码写的hash算法

private int hash(int hashCode) {

hashCode=hashCode^((hashCode>>>20)^(hashCode>>>12));

return hashCode^((hashCode>>>7)^(hashCode>>>4));

}

 

3、得到元素的对象,并且判断为空和不为空

if(entry==null) {

table[index] =new Entry(k,v,null);

useSize++;//使用位置被占用+1

}else if(entry!=null) {//说明说相同的值,挤压下去,形成链表

table[index] =new Entry(k,v,entry);

}

3.1、为空的话,说明没有相同的元素,也就形成不了链表,存入看,k,v和指向链表下一个的值为null,当前位置useSize得自增加一。

3.2、不为空,说明有相同的值,把老值挤压下去,形成链表,存入看,k,v和指向链表下一个

值不为空。

 

 

定义get方法

public V get(Kk) {

int index =getIndex(k,table.length);

if(table[index]==null) {

throw new NullPointerException();//报个空指针异常

}

//处理k存在的情况

return findValueByEqualKey(k,table[index]);

}

 

 

private V findValueByEqualKey(Kk, MyHashMap.Entry entry) {

if(k==entry.getKey() ||k.equals(entry.getKey())) {

return entry.getValue();

}else if (entry.next!=null) {//key不相等,hash相等

return findValueByEqualKey(k,entry.next);//调用递归找链表的下一个值

}

return null;

}

你可能感兴趣的:(hashmap)