#两个类,扩容,散列皆有详细的注释
1.顶层接口CMap
package com.cn.map;
import java.io.Serializable;
import java.util.Set;
/**
* 自定义map接口
* @author Mc
* @param <K>
* @param <V>
*/
public interface CMap<K,V> extends Serializable,Cloneable {
V put(K k,V v);
V get(K k);
/**
* 内部 Entry接口
* @param <K>
* @param <V>
*/
public abstract interface Entry<K,V>{
public K getKey();
public V getValue();
}
public Set<K> keySet();
}
2.hashmap实现类
package com.cn.map;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* map实现类
* @author Mc
*/
public class CHashMap<K, V> implements CMap<K, V>{
private static final Integer DEFAULT_LENGTH = 1 << 4;//默认长度16
private static final Double DEFAULT_ADD_FACTORY = 0.75;//负载因子
private static final Integer MAX_LEGTH = 1 << 30;//map数组的最大容量
private int useSize = 0; //槽点使用数量
private Entry<K, V> table[];//内部数组
private int size = DEFAULT_LENGTH;//当前容量
/**
* 无参构造器
*/
public CHashMap(){
initMap(DEFAULT_LENGTH);
}
public CHashMap(int size){
if(size <=0 )throw new IllegalArgumentException();
initMap(size);
}
/**
* 初始化 Map
* @param size 初始长度
* @param factory 负载因子
*/
private void initMap(int size) {
this.size = size;
this.table = new Entry[size];
}
/**
* 实现CMap接口中的抽象接口
* @param <K>
* @param <V>
*/
public class Entry<K, V> implements CMap.Entry<K, V>{
private V v;
private K k;
private Entry<K, V> next;
public Entry(K k,V v,Entry<K, V> next){
this.v = v;
this.k = k;
this.next = next;
}
@Override
public K getKey() {
return this.k;
}
@Override
public V getValue() {
return this.v;
}
}
@Override
public V put(K k, V v) {
if(k == null)putNullKey(k, v);
//判断当前槽数是否需要扩容
if(useSize > DEFAULT_ADD_FACTORY * size && size < MAX_LEGTH){
//需要扩容
System.out.println("------------------------hashMap is reSize-------------------------");
up2size();
}
//获取该存放的数组索引位置
int index = getIndex(k,table.length);
//假设槽点没有值,则放置在链表头
if(table[index] == null){
table[index] = new Entry<K,V>(k, v, null);
useSize ++;
return null;
}
V oldValue = putValueToIndex(k,v,index);
return oldValue;
}
/**
* 将kv放置在链表上
* @param k
* @param v
* @param index
* @return
*/
private V putValueToIndex(K k, V v, int index) {
Entry<K,V> entry = table[index];
//校验此链表上是否有重复
for (Entry<K,V> e = entry; e != null; e = e.next) {
if (e.k.equals(k) || e.k == k) {
V oldValue = e.v;
e.v = v;
return oldValue;
}
}
//无重复则占领链表头
table[index] = new Entry<K,V>(k, v, entry);
return null;
}
/**
* 计算索引
* @param k
* @param length
* @return
*/
private int getIndex(K k, int length) {
int hashCode = k.hashCode();
return hash(hashCode) & (length - 1);
}
/**
* 重算哈希值 此处是hashMap精髓中的精髓,皆为降低哈希碰撞
* @param hashCode
* @return
*/
private int hash(int hashCode) {
//hash32
hashCode = hashCode ^ ((hashCode >>> 20) ^ (hashCode >>> 12));
return hashCode ^ ((hashCode >>> 7) ^ (hashCode >>> 4));
}
/**
* MAP扩容
*/
private void up2size() {
Entry newTable[] = new Entry[size << 1];
//将老数据全部重新HASH散列
List<Entry<K,V>> list = new ArrayList<>();
for(CHashMap<K, V>.Entry<K, V> entry : table){
moveEntryToList(list,entry);
}
//正式扩容,重新散列
size = size << 1;
table = newTable;
useSize = 0;//槽点归零
for (Entry<K, V> entry : list) {
put(entry.getKey(), entry.getValue());
}
}
/**
* 将老table上的元素全部挪到list里面
* @param list
* @param entry
*/
private void moveEntryToList(List<CHashMap<K, V>.Entry<K, V>> list, CHashMap<K, V>.Entry<K, V> entry) {
if(entry == null)return;
if(entry.next == null){
list.add(entry);
}else{
//递归存入
list.add(entry);
moveEntryToList(list,entry.next);
}
}
@Override
public V get(K k) {
if(k == null)return getNullKey();
int index = getIndex(k, size);
return findValueByIndex(k,table[index]);
}
/**
* 根据索引获取值
* @param k
* @param entry
* @return
*/
private V findValueByIndex(K k, CHashMap<K, V>.Entry<K, V> entry) {
if(entry == null)return null;
if(entry.k.equals(k) || entry.k == k)return entry.v;
//递归获取
return findValueByIndex(k,entry.next);
}
/**
* 获取key为空的对象
* @return
*/
private V getNullKey(){
Entry<K, V> entry = table[0];
if(entry != null && entry.getKey() == null)return entry.v;
return null;
}
/**
* 放置key为空的对象
* @return
*/
private V putNullKey(K k,V v){
Entry<K, V> entry = table[0];
if(entry == null){
table[0] = new Entry<K, V>(k, v, null);
return null;
}
if(entry.k == null){
V oldValue = entry.v;
entry.v = oldValue;
return oldValue;
}
table[0] = new Entry<K, V>(k, v, entry);
return null;
}
/**
* 获取key的集合
*/
public Set<K> keySet(){
Set<K> set = new HashSet<>();
for(CHashMap<K, V>.Entry<K, V> entry : table){
moveEntryKeyToList(set,entry);
}
return set;
}
/**
* 将table元素的key存入list
* @param set
* @param entry
*/
private void moveEntryKeyToList(Set<K> set, CHashMap<K, V>.Entry<K, V> entry) {
if(entry == null)return;
if(entry.next == null){
set.add(entry.k);
}else{
//递归存入
set.add(entry.k);
moveEntryKeyToList(set,entry.next);
}
}
/**
* 测试一波
* @param args
*/
public static void main(String[] args) {
CMap<String,String> map = new CHashMap<>();
for(int i = 0;i < 500 ;i++){
map.put("key--" + i, "value--"+i);
}
System.out.println("=======================写死遍历=============================");
for(int i = 0;i < 500 ;i++){
System.out.println(map.get("key--" + i));
}
System.out.println("=======================keySet遍历=============================");
for (String key : map.keySet()) {
System.out.println(map.get(key) + "==>");
}
}
}