写在前面:
今天电话面试阿里,本来就 不抱希望。所以面试的时候问,我要怎么样发展,才可以复合阿里高级JAVA的要求呢?
面试官说,对于高级JAVA,要求基础好。
啥是基础,按我的理解,就是
1.数据结构
2.算法
3.JAVA基础
4.Spring源码
在十几年的学生生涯里,我深刻地明白:慢就是快——只有开始慢下来,后面才能快起来;少就是多——贪多永远就是泛泛而谈;专就是博——只有有一个“专”,才有立身之基,可以辐射到四周。
总而言之,为了更高的高度,必须夯实基础。
立个Flag,每周四篇博客,踏踏实实,每天进步一点!
正文:
啥是HashMap?
HashMap用的很多,用起来也很方便。它是怎么做到的呢?
我们首先看思路:
https://www.cnblogs.com/yuanblog/p/4441017.html
这篇文章写得很好,里面有句话说明白了HashMap的本质:
一个元素是链表的数组
// 这是HashMap中的部分源码,可以看到这个Node节点有我们熟悉的<K,V>键值对,并且还指向下一个节点
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
我们如果想写一个简单的HashMap,只需要完成它的数据结构就可以了,
也就是说
1.建立一个 链表数组
2.通过hash分配节点在哪个链表中
3.判断是更新key值还是在链表中插入
。。。
开始造轮子!
一、写一个K,V节点,这里为了体现山寨性,泛型用A,B
public class MyEntry<A,B> {
A a;
B b;
int hash;
MyEntry<A,B> next;
public MyEntry(){
}
public MyEntry(A a,B b){
this.a = a;
this.b = b;
}
}
二、MyHashMap的一些属性和方法
所谓方法未定,接口先行。因为是一个简易山寨版,所以我们目前只支持存和取两个方法。
public class MyHashMap<A,B> {
static final int MY_DEFAULT_INITIAL_CAPACITY = 8;
MyEntry<A,B>[] myTable;
int myCapacity;
// 默认容量
public MyHashMap(){
this.myCapacity = MY_DEFAULT_INITIAL_CAPACITY;;
}
// 指定容量
public MyHashMap(int capacity) {
this.myCapacity = capacity;
}
// hash 的最简单实现,直接模(容量-1) 得到数组下标
private int myHash(A a) {
return a.hashCode() % (myCapacity - 1);
}
public B put(A a, B b) {
return b;
}
public B get(A a) {
return null;
}
}
三、方法的具体实现
put方法完全体
public B put(A a, B b) {
int hash = myHash(a); // 计算hash
if (null == myTable) {
// myTable为空则初始化
myTable = new MyEntry[myCapacity];
}
// 如果这个地方就是空的话,直接放进去就可以了
if (null == myTable[hash]) {
myTable[hash] = new MyEntry<>(hash,a,b);
} else {
// 不是空,需要考虑key是否已经存在
// 存在则在原有key上更新value
// 不存在,则采取尾插
reSetValueOrInsert(a,b,myTable[hash]);
}
return b;
}
// 如果含有这个key则重置值
private void reSetValueOrInsert(A a,B b, MyEntry myEntry) {
// 如果相等,则更新value并返回true
if (myEntry.a.equals(a)) {
myEntry.b = b;
return;
}
// 不相等且已经是最后一个节点了,
// 把新的键值对插在最后
if (myEntry.next == null) {
myEntry.next = new MyEntry(myHash(a),a,b)
return;
}
// 都不满足则走到下个节点
reSetValueOrInsert(a, b, myEntry.next);
}
get方法完全体
public B get(A a) {
// 如果myTable 为空直接返回null
return myTable == null ? null : getValue(a);
}
// 否则根据a去链表中匹配
private B getValue(A a) {
int hash = myHash(a);
MyEntry it = myTable[hash];
while (null!=it && it.a.equals(a)) {
return (B)it.b;
}
return null;
}
四、完整的MyHashMap(存储取值实现)类
package com.ale.Try4st.myCollections;
public class MyHashMap<A,B> {
static final int MY_DEFAULT_INITIAL_CAPACITY = 8;
MyEntry<A,B>[] myTable;
int myCapacity;
public MyHashMap(){
this.myCapacity = MY_DEFAULT_INITIAL_CAPACITY;;
}
public MyHashMap(int capacity) {
this.myCapacity = capacity;
}
private int myHash(A a) {
return a.hashCode() % (myCapacity - 1);
}
public B put(A a, B b) {
int hash = myHash(a);
if (null == myTable) {
myTable = new MyEntry[myCapacity];
}
// 如果这个地方就是空的话,直接放进去就可以了
if (null == myTable[hash]) {
myTable[hash] = new MyEntry<>(hash,a,b);
} else {
// 不是空,需要考虑key是否已经存在
// 存在则在原有key上更新value
// 不存在,则尾插
reSetValueOrInsert(a,b,myTable[hash]);
}
return b;
}
private void reSetValueOrInsert(A a,B b, MyEntry myEntry) {
// 如果相等,则更新value并返回true
if (myEntry.a.equals(a)) {
myEntry.b = b;
return;
}
// 不相等且已经是最后一个节点了,
// 把新的键值对插在最后
if (myEntry.next == null) {
myEntry.next = new MyEntry(myHash(a),a,b);
return;
}
// 都不满足则走到下个节点
reSetValueOrInsert(a, b, myEntry.next);
}
public B get(A a) {
return myTable == null ? null : getValue(a);
}
private B getValue(A a) {
int hash = myHash(a);
MyEntry it = myTable[hash];
while (null!=it && it.a.equals(a)) {
return (B)it.b;
}
return null;
}
}
基本功能测试
public class MyHashMapTest {
public static void main(String[] args) {
MyHashMap<String,String> myHashMap = new MyHashMap<>();
System.out.println(myHashMap.put("阿乐","还行"));
System.out.println(myHashMap.put("阿乐","不错"));
System.out.println(myHashMap.put("阿乐","很强"));
System.out.println(myHashMap.put("小胖","小笨蛋"));
System.out.println(myHashMap.get("阿乐"));
System.out.println(myHashMap.get("小胖"));
System.out.println(myHashMap.get("xiaopang"));
}
}
输出结果
还行
不错
很强
小笨蛋
很强
小笨蛋
null
总结:
只需要70行代码就可以写一个HashMap的简化版出来,当然,这个简化版有很多阉割的地方。
后面有时间会写一个进阶版出来。
------------------------我是阿乐,CV熟练工,会一点JAVA------------------------