看到这个题,不要被吓到了,不会难的咱还不会一个简单的吗?
我们实现的简单的HashMap命名为 MyHashMap ,先确定整体的设计:
散列函数:hashCode()+除留余数法
冲突解决:链地址法
定义一个内部节点:相当于链表。
class Node<K, V> {
// 键值对
private K key;
private V value;
// 链表
private Node<K, V> next;
public Node(K key, V value) {
this.key = key;
this.value = value;
}
public Node(K key, V value, Node<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
}
主要有四个成员变量,其中桶数组作为装载数据元素的结构:
//默认容量
final int DEFAULT_CAPACITY = 16;
//负载因子
final float LOAD_FACTOR = 0.75f;
//HashMap的大小
private int size;
//桶数组
Node<K, V>[] buckets;
实现基础方法:
get :获取值
put :存入值
resize:扩容
public MyHashMap() {
size = 0;
buckets = new Node[DEFAULT_CAPACITY];
}
public MyHashMap(int initCapacity) {
size = 0;
buckets = new Node[initCapacity];
}
private int getIndex(K key, int length){
int hash = hash(key);
return Math.abs(hash) % length;
}
private int hash(K key) {
int h = 0;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
/**
* put方法
* @param key 键
* @param value 值
*/
public void put (K key, V value) {
if (size >= buckets.length * LOAD_FACTOR) {
resize();
}
putVal(key, value, buckets);
}
/**
* 将元素存入指定的node数组
*
* @param key
* @param value
* @param table
*/
private void putVal(K key, V value, Node<K, V>[] table) {
int index = getIndex(key,table.length);
Node<K,V> node = table[index];
// 待插入的位置为空
if (node == null) {
table[index] = new Node<>(key,value);
size++;
return;
}
// 待插入的位置不为空
while (node.next != null) {
//如果key相同,就覆盖掉
if ((node.key.hashCode() == key.hashCode())
&& (key == node.key || (node.key.equals(key)))) {
node.value = value;
return;
}
node = node.next;
}
// 插入到末尾
node.next = new Node<>(key, value);
size++;
}
/**
* 扩容
*/
private void resize() {
//创建一个两倍容量的桶数组
Node<K, V>[] newBuckets = new Node[buckets.length * 2];
//将当前元素重新散列到新的桶数组
rehash(newBuckets);
buckets = newBuckets;
}
/**
* 重新散列当前元素
*
* @param newBuckets 扩展后的桶
*/
private void rehash(Node<K, V>[] newBuckets) {
//map大小重新计算
size = 0;
//将旧的桶数组的元素全部刷到新的桶数组里
for (int i = 0; i < buckets.length; i++) {
//为空,跳过
if (buckets[i] == null) {
continue;
}
Node<K, V> node = buckets[i];
while (node != null) {
//将元素放入新数组
putVal(node.key, node.value, newBuckets);
node = node.next;
}
}
}
测试
public static void main(String[] args) {
MyHashMap<String, String> map = new MyHashMap();
for (int i = 0; i < 100; i++) {
map.put("刘华强" + i, "你这瓜保熟吗?" + i);
}
System.out.println(map.size());
for (int i = 0; i < 100; i++) {
System.out.println(map.get("刘华强" + i));
}
map.put("刘华强1","哥们,你这瓜保熟吗?");
map.put("刘华强1","你这瓜熟我肯定要啊!");
System.out.println(map.get("刘华强1"));
}