鉴于使用数组实现Map存在的一些问题,引入HashCode,实现HashMap的一些功能
/**
* Map编程优化
* Map的底层实现为数组+链表
* 1.提高查询效率,避免循环遍历,使用Hashcode快速定位存储位置
*
* Hashcode与equals的关系
* 1.equals相同的对象必然存在拥有相同的Hashcode值,反之不然
* 原因:根据存放规则,hashcode值相同的对象存放在同一数组,数组里面存放的则为链表,若Key值相同则覆盖,不同则向链表后添加;
* 所以equals相同的对象必然存放于对应的Hashcode数组位置,而同一Hashcode值对应的数组内可能会存放不同的对象,
* 所以Hashcode值相同的对象不一定相等,只是存放在数组内的位置相同
* @author Administrator
*
*/
public class MyMap02 {
//Entry[] arr = new Entry[999];
//map底层数组+链表,在数组里面存放链表,链表内存放对象的键值对数组Entry
MyLinkedList[] List = new MyLinkedList[999];
int size;
public void put(Object key,Object value){
Entry e = new Entry(key, value);
//通过hashcode值存储链表
int hash = key.hashCode();
//hash为负数的情况
hash = hash<0?-hash:hash;
int a = key.hashCode()%List.length;
if (List[a]==null) {
MyLinkedList list = new MyLinkedList();
//List[]为链表数组,list为链表对象,list存放在List[]中
List[a] = list;
//在链表list中存放键值对对象e
list.add(e);
}else{
MyLinkedList list = List[a];
//遍历链表,查询是否存在相同key值的对象
for (int i = 0; i < list.size(); i++) {
Entry e2 = (Entry) list.get(i);
if (e2.Key.equals(key)) {
e2.Value=value;
return;
}
}
List[a].add(e);
}
}
public Object get(Object key){
//return list[key.hashCode()%999].Value;
int a = key.hashCode()%List.length;
if (List[a]!=null) {
MyLinkedList list = List[a];
for (int i = 0; i < list.size(); i++) {
Entry e = (Entry) list.get(i);
if (e.Key.equals(key)) {
return e.Value;
}
}
}
return null;
}
public static void main(String[] args) {
MyMap02 map = new MyMap02();
map.put("aaa", "111");
map.put("bbb", "222");
map.put("ccc", "333");
System.out.println(map.get("aaa"));
}
}
引入HashCode可能会出现的问题及解决方法
1). Hash值相同的情况
在使用HashCode值存放对象时,可能出现两个对象Hash值相同的情况,由于Map的底层实现为数组+链表,通过HashCode值将对象对应放在数组中,如果出现Hash值相同的情况,则将这些对象依次放在存放在数组中的链表中,依次来解决HashCode重复的冲突问题。这也从内存关系上说明了HashCode值相同与Equals()为true的关系。
2). HashCode值为负的修正
通过一个三目运算符保证Hash值为正
//hash为负数的情况
hash = hash<0?-hash:hash;