声明:学基础,在校学生,本文所有内容来自书本和视频,然后通过自己的理解和筛选编写而来,如有理解不到位的写得不到位的地方,欢迎评论指错!!!(仅做学习交流)
笔者:Fhvk
微信:WindowsC-
HashMap
- 底层结构是哈希表,使用数组+链表的方式;同一个链表存储地址是一样的;
- 链表的每一个结点是一个Entry对象,四个部分:hash、key、value、next
- 添加元素,不是添加到链表的后面,面是添加到链表前面
- 哈希表的优点:添加快,查询也快(通过计算得到存储位置,不是通过比较)、无序的、key唯一
- 关键参数:默认主数组长度为:16、默认装填因子为0.75、每次主数组扩容为原来的2倍、JDK1.8当链表长度大于8,链表变成红黑树;
- 手写HashMap
public class MyHashMap {
//初始化主数组大小为16
private final int DEFAULT_INITIAL_CAPACITY = 16;
//定义size,键值对的数量Entry对象的数量节点的数量
int size;
//定义Entry对象数组引用
Entry[] table;
//构造
public MyHashMap() {
//初始化主数组,从这里可以看出map默认大小为16
table = new Entry[DEFAULT_INITIAL_CAPACITY];
}
//toString方法
public String toString() {
//创建缓冲区
StringBuilder sb = new StringBuilder("{");
//遍历大数组
for(int i = 0; i < table.length; i++) {
if(table[i] != null) { //不能为空
//获取当前索引的第一个节点
Entry e = table[i];
while(e != null) {//遍历存入
sb.append(e.getKey() + " = " + e.getValue() + ",");
e = e.next;
}
}
}
if(size != 0) { //元素个数不能为0
//将最后一个字符支除
sb.deleteCharAt(sb.length() - 1);
}
sb.append("}");
//返回String
return sb.toString();
}
//size()方法
public int size() {
return this.size;
}
//isEmpty()方法
public boolean isEmpty() {
rteurn this.size == 0;
}
public Object get(Object key) {
//计算哈希值
int hash = key.hashCode();
//计算存储位置
int index = hash % table.length;
//找值
Entry entry = null;
if(table[index] != null) {
Entry e = table[index];
while(e != null) {
if(entry.getKey().equals(key) && entry.hash == hash) {
entry = e;
break;
}
e = e.next;
}
}
return entry == null ? null : entry.value;
}
//添加方法
public void put(Object key, Object value) {
//计算哈希值
int hash = key.hashCode();
//计算存储位置
int index = hash % table.length;
//存储到指定位置
if(table[index] == null ) { //如果文位置为空
// 直接new一个放第一个
table = new Entry(hash, key, value, null);
}else {//如果该位置有元素
//先获取头
Entry entry = table[index];
while(entry != null) { //遍历
//判断键是否一样
if(entry.getKey().equals(key) && hash == entry.hash) {
//一样覆盖原值
entry.value = value;
return;
}
//向下移
entry = entry.next;
}
//没有找到就在创建一个插到第一个位置
Entry first = table[index];
table[index]= new Entry(hash, key, value, first);
}
//size++
size++;
}
//节点对象
static class Entry {
//哈希值,第一个键的哈希值
int hash;
//键
Object key;
//值
Object value;
//下一个节点
Entry next;
//构造给值
Entry(int hash, Object key, Object value, Entry next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
//get方法
public Object getKey() {
return this.key;
}
public Object getValue() {
return this.value;
}
}
}