简述
分享一个2年前自己实现的hashmap,查了下网上大多实现较为复杂,就献丑呈上。
MyHashMap
- 接口类
package com.sunyard.unified.csrt.spring.map;
public interface Map<K,Y> {
Y put(K k ,Y y);
Y get(K k);
int size();
boolean isEmpty();
interface Entry<K,Y> {
Y getValue();
K getKey();
@Override
int hashCode();
}
}
- 实现类
package com.sunyard.unified.csrt.spring.map;
/**
* <p>HashMap</p>
* 手写HashMap
* 1.7 -> 数组 + 链表
* 1.8 -> 数组 + 链表 + 红黑树
* @author :chaotan.liu
* @date :2020-07-30
*/
public class HashMap<K,V> implements Map<K,V> {
Node<K,V>[] table = new Node[16];
int size =0;
@Override
public V put(K k, V v) {
int i = Math.abs( k.hashCode() % 16);
Node<K,V> node = table[i];
if(node == null){
table[i] = new Node<>(i,k,v,null);
}else {
//头部插入 ,个人认为插入效率高 ,内存冗余大 实测100000条数据耗时31毫秒 MemoryCost: 29297744KB
table[i]= new Node<>(i,k,v,node);
//尾部插入 递归算法 100000条数据耗时15031毫秒 MemoryCost: 29297968KB
// setNode(k, v, i, node);
//尾部插入共耗时15101毫秒 MemoryCost: 29298032KB
// while (node != null) {
// if (node.getKey().hashCode() == k.hashCode()) {
// node.v = v;
// break;
// } else {
// if (node.next == null) {
// node.next = new Node<>(i, k, v, null);
// break;
// } else {
// node = node.next;
// }
// }
// }
}
size++;
return v;
}
/**
* 递归实现尾部插入链表
* @param k
* @param v
* @param index
* @param e
*/
private void setNode(K k, V v, int index, Node<K, V> e) {
if( e.getKey().hashCode() == k.hashCode()){
e.v = v;
}
if(e.next == null){
e.next = new Node<>(index,k,v,null);
}
else {
setNode(k,v,index,e.next);
}
}
private Node<K, V> getNode(K k, Node<K, V> e) {
if(e == null){
return null;
}
if( e.getKey().hashCode() == k.hashCode()){
return e;
}else {
return getNode(k,e.next);
}
}
@Override
public V get(K k) {
if( isEmpty()){
return null;
}
int i = Math.abs( k.hashCode() % 16);
Node<K,V> node = table[i];
if(node == null){
return null;
}
//递归算法获取 共耗时12174毫秒
//MemoryCost: 38265784KB
Node<K, V> node1 = getNode(k, node);
return node1 == null ? null : node1.getValue();
// while方式获取 共耗时12287毫秒 MemoryCost: 38385472KB 两个方式差不多
// while ( node != null){
// if( node.getKey().hashCode() == k.hashCode()){
// return node.getValue();
// }
// if(node.next != null){
// node = node.next;
// }else {
// break;
// }
// }
// return null;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
if(size() == 0){
return true;
}
return false;
}
static class Node<K,V> implements Map.Entry<K,V>{
int hash;
final K k;
V v;
Node<K,V> next;
public Node(int hash, K k, V v, Node<K, V> next) {
this.hash = hash;
this.k = k;
this.v = v;
this.next = next;
}
@Override
public V getValue() {
return v;
}
@Override
public K getKey() {
return k;
}
@Override
public final String toString() { return k + "=" + v; }
}
}
- 测试类
package com.sunyard.unified.csrt.spring.map;
//import java.util.Map;
//import java.util.HashMap;
/**
* <p></p>
*
* @author :chaotan.liu
* @date :2020-07-30
*/
public class MyMaptest {
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
r.gc();//计算bai内存前先垃圾回收du一次
Map<String,String> hashMap = new HashMap();
long start = System.currentTimeMillis();
long startMem = r.freeMemory(); // 开始Memory
for (int i=0;i<100000;i++){
hashMap.put(i+"优雅的key","柳晁潭"+i);
}
for (int i=0;i<100000;i++){
hashMap.put(i+"优雅的key","吴思思"+i);
}
for (int i=0;i<100000;i++){
// System.out.println(hashMap.get(i+"hahah"));
System.out.println(hashMap.get(i+"优雅的key"));
}
long end = System.currentTimeMillis();
long endMem =r.freeMemory(); // 末尾Memory
System.out.println("共耗时"+(end-start)+"毫秒");
System.out.println("MemoryCost: "+String.valueOf((startMem- endMem))+"KB");
}
}
//共耗时14099毫秒
//MemoryCost: 39800888KB
//hash 共耗时533毫秒
//MemoryCost: 28301384KB
唠嗑
自己实现的简单map速率确实差了很多,占用的空间也较大,比较hashmap不仅仅实现了简单的存取。
只用于理解hashmap的实现原理,感兴趣的可以撸下来康康。