HashMap的数据结构是数组+链表,之前的博客中有自定义的数组列表和链表,这里的数组和链表就是使用之前自定义的数组列表和链表。
实现的方法有put(K k,V v),get(K k),clear(),containsKey(K k),replace(K k,V v),remove(K k),不支持null值。
确定数组下标的方式直接用key的hashcode和数组容量进行取余运算,没有使用key.hash & (array.length-1)这种方式,道理一样,但后者效率比前者高一些。
下面是代码:
MyArrayList和MyLinkedList的实现参考之前的博客。
public class MyHashMap<K,V> {
//实际存储的key-value键值对的个数
public transient int size;
//当前数组容量
private int arrayCapacity;
//扩容判断的负载因子
private float loadFactor=0.75f;
//扩容的阈值
private int threshold;
private MyArrayList<MyLinkedList<NodeEntry>> arrayList;
private class NodeEntry{
public K key;
public V value;
public NodeEntry(K key, V value) {
super();
this.key = key;
this.value = value;
}
/**
* 重写hashCode和equals
*/
@Override
public int hashCode() {
// TODO Auto-generated method stub
return this.key.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof MyHashMap.NodeEntry)){
return false;
}
NodeEntry entry=(NodeEntry) obj;
return this.key.equals(entry.key)&&this.value.equals(entry.value);
}
@Override
public String toString() {
return "NodeEntry [key=" + key + ", value=" + value + "]";
}
}
//两个构造方法
public MyHashMap() {
this.arrayList=new MyArrayList<MyLinkedList<NodeEntry>>();
this.arrayCapacity=arrayList.currentCapacity;
this.threshold=(int) (arrayCapacity*loadFactor);
}
public MyHashMap(int capacity,float loadFactor) {
this.arrayList=new MyArrayList<MyLinkedList<NodeEntry>>(capacity);
this.arrayCapacity=arrayList.currentCapacity;
this.loadFactor=loadFactor;
this.threshold=(int) (arrayCapacity*loadFactor);
}
/**
* 存储数据,如果key已经存在,则新value覆盖旧value,并返回旧value
* @param k key
* @param v value
* @return
*/
public V put(K k,V v){
if(k==null){
throw new IllegalArgumentException("key不能为null");
}
if(containsKey(k)){
return replace(k, v);
}
MyLinkedList<NodeEntry> linkedList;
arrayCapacity=arrayList.currentCapacity;
int i=k.hashCode()%arrayCapacity;
linkedList=arrayList.get(i);
if(linkedList==null){
linkedList=new MyLinkedList<NodeEntry>();
}
linkedList.addNode(new NodeEntry(k, v));
addNodeEntry(i, linkedList);
size++;
return null;
}
/**
* 根据key获取元素
* @param k
* @return
*/
public V get(K k){
int i=k.hashCode()%this.arrayCapacity;
MyLinkedList<NodeEntry> linkedList=this.arrayList.get(i);
if(linkedList!=null){
for (NodeEntry entry : linkedList) {
if(entry.key==k||k.equals(entry.key)){
return entry.value;
}
}
}
return null;
}
private void addNodeEntry(int index,MyLinkedList<NodeEntry> linkedList){
if(size>=threshold&&this.arrayList.get(index)!=null){
resizeArrayCapacity(this.arrayCapacity*2);
}
this.arrayList.set(index, linkedList);
this.arrayList.size++;
}
/**
* 数组进行扩容,并将旧数组中的元素重新放到新数组中
* @param newCapacity 新数组的容量
*/
void resizeArrayCapacity(int newCapacity){
//根据容量创建一个新数组
MyArrayList<MyLinkedList<NodeEntry>> newlist=new MyArrayList<MyLinkedList<NodeEntry>>(newCapacity);
MyLinkedList<NodeEntry> tempLinkedList = null;
//遍历每一个链表的节点,获取新的数组下标,并将节点存放到新数组中去
for (int i = 0; i < arrayList.currentCapacity; i++) {
MyLinkedList<NodeEntry> nodeList=arrayList.get(i);
if (nodeList!=null) {
//System.err.println(nodeList.size);
for (NodeEntry nodeEntry : nodeList) {
//System.err.println(nodeEntry.key);
int index=nodeEntry.key.hashCode()%newCapacity;
//根据生成的数组下标,获取链表,如不存在则生成新的
tempLinkedList=newlist.get(index);
if(tempLinkedList==null){
tempLinkedList=new MyLinkedList<NodeEntry>();
}
//链表中添加元素
tempLinkedList.addNode(nodeEntry);
//链表添加到新的list中
newlist.set(index, tempLinkedList);
}
}
}
this.arrayList=newlist;
this.arrayCapacity=newCapacity;
this.threshold=(int) (arrayCapacity*loadFactor);
}
/**
* 清空map
*/
public void clear(){
arrayList.clear();
size=0;
}
/**
* 判断map是否存在该key
* @param k
* @return
*/
public boolean containsKey(K k) {
int i=k.hashCode()%this.arrayCapacity;
MyLinkedList<NodeEntry> linkedList=this.arrayList.get(i);
if(linkedList!=null){
for (NodeEntry entry : linkedList) {
if(entry.key==k||k.equals(entry.key)){
return true;
}
}
}
return false;
}
/**
* 根据key和value替换元素
* @param k
* @param v
* @return
*/
public V replace(K k,V v){
int i=k.hashCode()%this.arrayCapacity;
MyLinkedList<NodeEntry> linkedList=this.arrayList.get(i);
V oldValue=null;
if(linkedList!=null){
for (NodeEntry entry : linkedList) {
if(entry.key==k||k.equals(entry.key)){
oldValue=entry.value;
entry.value=v;
return oldValue;
}
}
}
return oldValue;
}
/**
* 根据key删除元素
* @param k
* @return
*/
public V remove(K k){
V oldValue=null;
if(containsKey(k)){
oldValue=get(k);
int i=k.hashCode()%arrayCapacity;
MyLinkedList<NodeEntry> linkedList=arrayList.get(i);
if(linkedList!=null){
NodeEntry entry=new NodeEntry(k, oldValue);
try {
linkedList.deleteNode(entry);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return oldValue;
}
public static void main(String[] args){
MyHashMap<String, Object> map=new MyHashMap<String, Object>();
map.put("name", "张三");
map.put("age", "11");
map.put("add", "北京");
map.remove("age");
map.remove("name");
map.put("age", "655");
System.err.println(map.get("age"));
System.err.println(map.get("name"));
//System.err.println(map.containsKey("990"));
}
}