HashMap1.8后使用红黑树有一个阈值,为8-1,只有链表的长度达到或者超过才会转换成黑红树。
为什么要后面要加红黑树,无非是链表的查询效率太低,但为什么不直接抛弃链表那?还要搞个大于7在转换(●ˇ∀ˇ●)?
第一步创建了一个项目:
第二步创建一个接口:map 贼简单主要就算方法的声明和长度、存储的对象属性
package mymap.mymap;
/**
*
* @author hong
*这个是自定义1.7版本map的顶级接口
* @param <K>
* @param <V>
*/
public interface map<K,V> {
/**
* 向map中添加数据
* @param k
* @param v
* @return
*/
public V put(K k, V v);
/**
* 从map中获取数据
* @param k
* @return
*/
public V get(K k);
/**
* 记录map的长度
* @return
*/
public int size();
interface Entry<K,V>{
public K getKey();
public V getValue();
}
}
第三步创建具体的实现类 其实很简单就是编写具体的实现,主要获取下标哪儿不能是负数
package mymap.mymap.Impl;
import mymap.mymap.map;
public class HashMap<K, V> implements map<K, V> {
int size = 0;
// 生成数组,存储对象是Entry
Entry<K, V> table[] = null;
// 通过无参构造函数给数组赋值,初始长度为16
public HashMap() {
table = new Entry[16];
}
/**
* put之前 key>hash>数组下标内容>当前内容是否为null
*/
@Override
public V put(K k, V v) {
// 先获得key值的哈希值,这个哈希值就是我们定义的数值的下标
int index = hash(k);
// 完整的hash值
int hash = k.hashCode();
// 数组的特性,查询快,通过哈希值下标去查询数组中这个位置是否由数据
Entry<K, V> entry = table[index];
// 如果没有数据,则表示改内存为null,我们直接将数据put进去,next为null
if (entry == null) {
table[index] = new Entry<>(k, v, null, hash);
size++;
} else {
// 如果该下标下面的内存空间有数据,则将这个内存空间转换成链表 next不再为null
table[index] = new Entry<>(k, v, entry, hash);
}
// 最后返回值
return table[index].getValue();
}
private int hash(K k) {
int index = k.hashCode() % 16;
// 如果这个哈希值是负的则负负得正
return index > 0 ? index : -index;
}
@Override
public V get(K k) {
// 首先获取到他的下标
int index = hash(k);
// hash值
int hash = k.hashCode();
// 获取数组中的数据
Entry<K, V> entry = table[index];
// 判断查询的值是否为空
if (entry == null | size == 0) {
return null;
}
// 递归遍历
return find(k, entry);
}
private V find(K k, Entry<K, V> entry) {
// 寻找相等的key
if (k == entry.getKey() || k.equals(entry.getKey())) {
return entry.getValue();
} else {
// 如果没有找到,然后next还不为null,递归
if (entry.next != null) {
return find(k, entry.next);
}
}
return null;
}
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
/**
* hashmap底层是一个数组,数组里面存储的就是我们的Entry对象
*
* @author hong
*
* @param <K>
* @param <V>
*/
class Entry<K, V> implements map.Entry<K, V> {
K k;
V v;
Entry<K, V> next;
int hash;
public Entry(K k, V v, Entry<K, V> next, int hash) {
super();
this.k = k;
this.v = v;
this.next = next;
this.hash = hash;
}
@Override
public K getKey() {
// TODO Auto-generated method stub
return k;
}
@Override
public V getValue() {
// TODO Auto-generated method stub
return v;
}
}
}
最后测试一下