Java04 容器(之底层原理b)
* HashMap底层实现使用了哈希表(数据结构)
* 基本:数组Array+链表Linked(结合,取长补短)
* 链表长度大于8时,链表转换为红黑树(提高查询效率)
* 约定:两个内容相同(equals=True)的对象有相等的哈希code
*
*
* 底层介绍:
* HashMap的结构(也称:Entry位桶数组)
* 0 |hash-key-value-next|-->|hash-key-value-next|-|hash-key-value-next|
* 1 |hash-key-value-next|-->|hash-key-value-next|-|hash-key-value-next|
* ...
* 15 |hash-key-value-next|-->|hash-key-value-next|-|hash-key-value-next|
*
* 存储具体过程:
* (哈希算法1)相除取余法:使用key对象的哈希code,数组长度约定为2的整数幂,默认为16(当达到0.75*数组长度,数组大小扩容*2)
* 哈希code除以数组长度16,得到的余数为哈希值,作为上面的16个分组中的1个,整个数据块接在尾端next上面
* 改进:哈希code按位与(数组长度-1)
* 淘汰的a, 除于哈希值,退化为链表;
* 淘汰的b, 除于1,退化为数组
一个简单的Hashmap例子,只有简单的插入功能(实现了相同key覆盖)哦,(想要其他功能打印或者读取值的可以再补充),效果如下:
public class SxtHashMap01 {
Node2[] tabel;
int size;//存放键值对个数
//构造器
public SxtHashMap01(){
tabel = new Node2[16];
}
//方法1:输入方法
public void put(Object key, Object value){
Node2 newNode = new Node2();
/**
* 步骤1:定义插入的新节点的信息
*/
//Node2类里面4个属性,分别描述属性获取值的方法
newNode.hash = myHash(key.hashCode(),tabel.length);//通过方法myHash获得
//通过赋值符=获得
newNode.key = key;
newNode.value = value;
newNode.next = null;
/**
* 步骤2:根据信息,进行遍历(利用不实际存在的辅助节点temp和iterLast)
*/
boolean keyno_Repeat = true;
Node2 temp = tabel[newNode.hash];
Node2 iterLast = null;//正在遍历最后一个元素
if(temp==null){//如果此处数组元素为空,则直接将新节点放进去
tabel[newNode.hash] = newNode;
size++;
}else{//如果此处数组元素不为空,遍历该数组对应的列表
while (temp!=null){
//key如果重复,则覆盖
if(temp.key.equals(key)){
keyno_Repeat = false;
System.out.println("重复之前的节点: "+temp.key+"="+temp.value);
temp.value=value;
System.out.println("重复,利用新节点覆盖: "+temp.key+"="+temp.value);
break;//直接跳出循环
}else{
//key不重复,则遍历下一个(跳到循环再判断是否key重复)
iterLast = temp;
temp=temp.next;
}
//key如果没有重复,插入新节点
if(keyno_Repeat) {
iterLast.next = newNode;
System.out.println("abc"+iterLast.next);
size++;
}
}
}
}
/**
* 利用hashcode得到hash值
* @param v hashcode
* @param length 数组长度
* @return hash值
*/
//方法1.1:读取Hash值方法
public int myHash(int v,int length){
System.out.println("put新节点:");
System.out.println("hash in myHash按位与:"+(v&(length-1)));//效率更高
System.out.println("hash in myHash除以:"+(v%(length)));//两种都是为了分散存储
return v&(length-1);
}
public static void main(String[] args) {
SxtHashMap01 m = new SxtHashMap01();
m.put(10,"aa");
m.put(20,"bb");
m.put(30,"cc");
m.put(20,"ssss");
m.put(50,"hhh");
System.out.println("存放键值对个数"+m.size);
System.out.println(m);
}
}