定義一個map接口
/**
* Created by jiangcaijun on 2017/6/8.
* 定義一個map的接口
*/
public interface CustomMap<K,V> {
V put(K key,V value);
V get (K key);
int size();
//定義一個內部接口
//能夠根據Entry對象拿到這個對象的key和value
interface Entry<K,V>{
K getKey();
V getValue();
}
}
hashmap類,實現該map接口
/**
* Created by jiangcaijun on 2017/6/8.
* 定義一個customMap的實現類
*/
public class CustomHashMap<K,V> implements CustomMap<K,V> {
private static Integer defaultLength = 16;//定義數組長度(定義成2的倍數)
private static float defaultLoad=0.75F;//定義負載因子(超過這個因子就會擴容)
private Entry<K,V>[] table =null;//定一個數組,盛放Entry對象
private int size=0;//定義一個常量,用來記錄hashmap元素個數
public CustomHashMap(){
this(defaultLength,defaultLoad);
}
public CustomHashMap(int length, float load){
if(length < 0){
throw new IllegalArgumentException("Illegal length" + length);
}
if(load > 0.0F && !Float.isNaN(load)) {
this.defaultLoad = load;
this.defaultLength = length;
table = new Entry[defaultLength];
} else {
throw new IllegalArgumentException("Illegal load: " + load);
}
}
@Override
public V put(K key, V value) {
int index = getIndex(key,table.length);
Entry<K,V> entry = table[index];
if(entry == null){
table[index] = new Entry(key,value,null,index);
}else if(entry != null){
table[index] = new Entry(key,value,entry,index);
}
size++;
if(size > defaultLength*defaultLoad){
resize();
}
return table[index].getValue();
}
@Override
public V get(K key) {
int index = getIndex(key,table.length);
if(table[index] == null){
return null;
}
return foundValueByKey(key,table[index]);
}
private V foundValueByKey(K key, Entry<K, V> entry) {
if( key == entry.getKey() || key.equals(entry.getKey())){
return entry.getValue();
}else if(entry.next != null){
return foundValueByKey(key,entry.next);
}
return null;
}
@Override
public int size() {
return this.size;
}
class Entry<K,V> implements CustomMap.Entry<K, V>{
K key;
V value;
Entry<K,V> next;
int index;//記錄下標
Entry(K k,V v,Entry<K,V> n,int inx){
key=k;
value=v;
index=inx;
next=n;//數組第一個元素的下一個元素
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
}
private int getIndex(K key, int length){
int m = length -1 ;
return key.hashCode() & m; //數值上等於key.hashCode() % length
}
//hashmap擴容
private void resize() {
Entry<K,V>[] newTable = new Entry[2*defaultLength];
transfer(newTable);
}
private void transfer(Entry<K, V>[] newTable) {
System.out.println("transfer 擴容");
Entry[] src = table; //src引用了舊的Entry數組
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) { //遍歷舊的Entry數組
Entry<K,V> e = src[j]; //取得舊Entry數組的每一個元素
if (e != null) {
src[j] = null;//釋放舊Entry數組的對象引用(for循環後,舊的Entry數組再也不引用任何對象)
do {
Entry<K,V> next = e.next;
int i = getIndex(e.key, newCapacity); //從新計算每一個元素在數組中的位置
e.next = newTable[i]; //newTable[i]的引用賦給了e.next,也就是使用了單鏈表的頭插入方式,同一位置上新元素總會被放在鏈表的頭部位置;這樣先放在一個索引上的元素終會被放到Entry鏈的尾部(若是發生了hash衝突的話);
newTable[i] = e; //將元素放在數組上
e = next; //訪問下一個Entry鏈上的元素
} while (e != null);
}
}
table = newTable;
defaultLength = 2*defaultLength; //更新數組長度
}
public static void main (String[] args){
CustomHashMap<String,String> map = new CustomHashMap<String,String>();
for(int i = 0; i < 100; i++){
map.put(i+"",i+"");
}
for(int i = 0; i < 100; i++){
System.out.println("map取值: "+ i + " = "+map.get(i+""));
}
}
}
參考連接: