前言:底层数据结构的简易实现,后续再更改。找了一篇博客
底层数据结构
Map接口
package hashMap;
// 底层map接口
public interface Map<K, V> {
// map中元素个数
int size();
// 插入
V put(K key, V val);
// 根据key获取val
V get(K key);
// 底层entry
interface Entry<K, V>{
K getKey();
V getValue();
V setValue(V val);
}
}
HashMap实现
package hashMap;
public class HashMap<K, V> implements Map<K, V> {
// 数组+链表,不考虑红黑树
Node<K, V>[] table = null; // table
// 初始化容量为16
final private static int defaultLength = 16;
// 装载因子
final private float loadFactor = 0.75f;
// 元素个数
private int size;
// 容量
private static int length;
@Override
public int size() {
return this.size;
}
// 添加元素
@Override
public V put(K key, V val) {
// 1、初始化
if(table == null){
table = new Node[defaultLength];
length = defaultLength;
}
// 2、通过hash算法,计算待插入的下标,i = (n - 1) & hash
int index = position(key, length);
// 若元素的个数size 大于 桶的尺寸*加载因子,执行扩容
if(size > length * loadFactor){
resize();
}
// 判断待添加位置是否有链表结点
Node<K, V> node = table[index];
if(node == null){
table[index] = new Node<K, V>(key, val, null);
size++;
}else{
if(key == node.getKey() || key.equals(node.getKey()))
return node.setValue(val); // 替换旧值
else{
// 采取前插的方法
table[index] = new Node<K, V>(key, val, node);
size++;
}
}
return null;
}
// 扩容
private void resize() {
// 1、创建新的table
Node<K, V>[] tmp = new Node[length << 1];
// 2、移动
Node<K, V> node = null;
for(int i = 0; i < table.length; i++){
node = table[i];
while(node != null){
int index =position(node.getKey(), tmp.length);
// 保存结点的下一个位置
Node<K, V> next = node.next;
node.next = tmp[index]; // 采用前插结点
tmp[index] = node;
node = next; // 移动到下一个位置
}
}
// 替换旧的table
table = tmp;
length = tmp.length;
}
// 这里面就是利用了原本hashMap的hash()
private int position(K key, int length){
int h;
int tmp = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
return tmp & (length - 1);
}
@Override
public V get(K key) {
if(table != null){
int index = position(key, length);
Node<K, V> node = table[index];
// 遍历链表
while(node != null){
if(key.equals(node.getKey())){
return node.getValue();
}else{
node = node.next; // 向后移动
}
}
}
return null;
}
// 链表结点
static class Node<K, V> implements Map.Entry<K, V>{
K key;
V value;
// 下一个链表结点
Node<K, V> next;
// 构造链表结点
public Node(K key, V value, Node<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return this.key;
}
@Override
public V getValue() {
return this.value;
}
@Override
public V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue; // 更新值,返回旧值
}
}
}
还需测试
// 在原hashMap中添加一个测试方法
public void print() {
System.out.println("===============================");
if (table != null) {
Node<K, V> node = null;
for (int i = 0; i < table.length; i++) {
node = table[i];
System.out.print("下标[" + i + "]");
// 遍历链表
while (node != null) {
System.out.print("[" + node.getKey() + ":" + node.getValue() + "]");
if (node.next != null) {
node = node.next;
} else {
// 到尾部元素
node = null;
}
}
System.out.println();
}
}
}
package hashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("ab", 2);
map.put("cd", 3);
System.out.println(map.get("ab"));
System.out.println("size " + map.size());
map.put("ab", 3);
System.out.println(map.get("ab"));
map.print();
}
}