手写HashMap
看完jdk 1.7和1.8的源码之后, 受源码的启发 手写一下HashMap,主要体会思想和原理
基于Arraylist集合方式实现:
package com.shanheyongmu.map; import java.util.ArrayList; import java.util.List; /** * 基于Arraylist集合方式实现 * @ClassName ArraylistHashMap **/ public class ArraylistHashMap<K, V> { private List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>(); class Entry<K, V> { K k; V v; Entry next; public Entry(K k, V v) { this.k = k; this.v = v; } } public void put(K k, V v) { entries.add(new Entry<>(k, v)); } public V get(K k) { for (Entry<K, V> entry : entries) { if (entry.k.equals(k)) { return entry.v; } } return null; } public static void main(String[] args) { ArraylistHashMap<String, String> arraylistHashMap = new ArraylistHashMap<>(); arraylistHashMap.put("blog", "blog1"); arraylistHashMap.put("test", "test1"); System.out.println(arraylistHashMap.get("test")); } }
总结:
根据key查询时间复杂度为o(n),效率非常低。
基于数组下标方式实现HashMap:
package com.shanheyongmu.map; /** * 基于数组下标方式实现HashMap * @param <K> * @param <V> */ public class ExtHashMap<K, V> { private Entry[] entrys = new Entry[10000]; class Entry<K, V> { public K k; public V v; public Entry(K k, V v) { this.k = k; this.v = v; } } public void put(K k, V v) {
//取模方式 int index = k.hashCode() % entrys.length; entrys[index] = entrys[index]; } public V get(K k) { int index = k.hashCode() % entrys.length; return (V) entrys[index].v; } public static void main(String[] args) { ExtHashMap<Object, String> hashMap = new ExtHashMap<>(); hashMap.put("a", "a"); hashMap.put(97, "97"); System.out.println(hashMap.get("a")); } }
Hash碰撞问题:
原因:hashcode值相同,内容值不同
通过jdk HashMap代码Entry<k,v> next和 put 上面代码还是有欠缺没有的问题 解决hash碰撞问题和增加遍历链表数据和key为null 增加代码如下
基于数组+链表方式实现:
package com.shanheyongmu.map; /** * 基于数组+链表方式实现 * @param <K> * @param <V> */ public class ExtHashMap<K, V> { private Entry[] entrys = new Entry[10000]; class Entry<K, V> { public K k; public V v; Entry<K,V> next; public Entry(K k, V v) { this.k = k; this.v = v; } } public void put(K k, V v) { //数组 + 链表实现 hash算法
int index = k == null ? 0 : k.hashCode() % objects.length;
//判断key是否冲突 Entry oldEntry = entrys[index]; if(oldEntry == null){ //key 没有发生hash碰撞的问题 entrys[index] = new Entry<K,V>(k,v); }else { // 发生hash碰撞则存放到链表后面 oldEntry.next = new Entry<K,V>(k,v); } entrys[index] = entrys[index]; } public V get(K k) { //遍历链表数据 int index = k == null ? 0 : k.hashCode() % entrys.length; for (Entry<K, V> oldEntry = entrys[index]; oldEntry != null; oldEntry = oldEntry.next) { if (oldEntry.k == null || oldEntry.k.equals(k)) { return oldEntry.v; } } return null; } public static void main(String[] args) { ExtHashMap<Object, String> hashMap = new ExtHashMap<>(); hashMap.put("a", "a"); hashMap.put(97, "97"); System.out.println(hashMap.get("a")); } }
早年同窗始相知,三载瞬逝情却萌。年少不知愁滋味,犹读红豆生南国。别离方知相思苦,心田红豆根以生。