定义:用于存储Key-Value键值对集合,
存储结构:线性链表(数组+链表)。数组:固定长度,索引效率高,增删效率低-----链表:长度不固定,索引效率低,增删效率高
散列值特点:同一对象调用多次hashcode()方法,必须返回相同的数值。(幂等)
如果两个对象根据equals()方法比较是相等的,那么两个对象调用hashcode()方法返回的结果必须相等;
if(a==b) a.hashcode()==b.hashcode()
如果两个对象的equals()方法比较是不相等的,那么两个对象调用hashcode()方法返回的结果不一定不相等
hash算法实现:取模,求与,线性探测,其他
public interface Map<K,V> {
//向hashMap中插入值
public V put(K k,V v);
//根据key获取hashMap中的值
public V get(K k);
//获得集合中元素的个数
public int size();
//获取集合中,键值对的对象
interface Entry<K,V>{
K getKey();
V getValue();
V setValue(V v);
}
}
package HashMap;
public class HashMap<K, V> implements Map<K, V> {
//数据存储的结构==>数组+链表
Node<K,V>[] array=null;
//数组/哈希桶的长度
private static int defaultLength=16;
//加载因子/扩容因子
private static double factor=0.75D;
//集合中的元素个数
private int size;
//测试打印函数
public void print() {
System.out.println("===============================");
if(array!=null) {
Node<K, V> node=null;
for (int i = 0; i < array.length; i++) {
node=array[i];
System.out.print("下标["+i+"]");
//遍历链表
while(node!=null) {
System.out.print("["+node.getKey()+":"+node.getValue()+"]");
if(node.next!=null) {
node=node.next;
}else {
//到尾部元素
node=null;
}
}
System.out.println();
}
}
}
//put元素方法
@Override
public V put(K k, V v) {
//1.懒加载机制,使用的时候进行分配
if(array==null) {
array=new Node[defaultLength];
}
//2.通过hash算法,计算出具体插入的位置
int index=position(k,defaultLength);
//扩容。判断是否需要扩容
//扩容的准则,元素的个数 大于 桶的尺寸*加载因子
if(size > defaultLength*factor) {
resize();
}
//3.放入要插入的元素
Node<K, V> node=array[index];
if(node==null) {
array[index]=new Node<K,V>(k,v,null);
size++;
}else {
if(k.equals(node.getKey()) || k==node.getKey()) {
return node.setValue(v);
}else {
array[index]=new Node<K,V>(k,v,node);
size++;
}
}
return null;
}
//扩容,并且重新排列元素
private void resize() {
//翻倍扩容
//1.创建新的array临时变量,相当于defaultlength*2
Node<K, V>[] temp=new Node[defaultLength << 1];
//2.重新计算散列值,插入到新的array中去。 code=key % defaultLength ==> code=key % defaultLength*2
Node<K, V> node=null;
for (int i = 0; i < array.length; i++) {
node=array[i];
while(node!=null) {
//重新散列
int index=position(node.getKey(),temp.length);
//插入头部
Node<K, V> next = node.next;
//3
node.next=temp[index];
//1
temp[index]=node;
//2
node=next;
}
}
//3.替换掉老array
array=temp;
defaultLength=temp.length;
temp=null;
}
private int position(K k,int length) {
int code=k.hashCode();
//取模算法
return code % (length-1);
//求与算法
//return code & (defaultLength-1);
}
@Override
public V get(K k) {
if(array!=null) {
int index=position(k,defaultLength);
Node<K, V> node=array[index];
//遍历链表
while(node!=null) {
//如果key值相同返回value
if(node.getKey()==k)
return node.getValue();
else
//如果key值不同则调到下一个元素
node=node.next;
}
}
return null;
}
@Override
public int size() {
return size;
}
static class Node<K,V> implements Entry<K,V>{
K key;
V value;
Node<K,V> next;
public Node(K key, V value, Node<K, V> next) {
super();
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return this.key;
}
@Override
public V getValue() {
return this.value;
}
@Override
public V setValue(V v) {
V oldValue=this.value;
this.value=v;
return oldValue;
}
}
}
public class Test {
public static void main(String[] args) {
HashMap<String, String> map=new HashMap<String, String>();
map.put("001号", "001");
map.put("002号", "002");
map.put("003号", "003");
map.put("004号", "004");
map.put("005号", "005");
map.put("006号", "006");
map.put("007号", "007");
map.put("008号", "008");
map.put("009号", "009");
map.put("010号", "010");
map.put("011号", "011");
map.print();
System.out.println("========>"+map.get("009号"));
}
}