前言
- 在Java集合中,Map是一种特殊的集合,原因在于这种集合容器并不是保存的单个元素,而是一个个的key-value键值对。HashMap是基于哈希表的Map接口的实现,在项目开发中,这种集合使用是非常广泛的,本文主要就是对HashMap的底层原理做个剖析。
HashMap特点
- HashMap是基于哈希表的Map接口实现。
- HashMap底层采用的是Entry数组和链表实现。
- HashMap是采用key-value形式存储,其中key是可以允许为null但是只能是一个,并且key不允许重复(如果重复则新值覆盖旧值)。
- HashMap是线程不安全的。HashMap存入的顺序和遍历的顺序有可能是不一致的。
- HashMap保存数据的时候通过计算key的hash值来去决定存储的位置。
话不多说上代码
package hashMap;
2
3 public class MyHashMap<K, V> {
4
5 private Entry<K, V>[] table;//Entry是hashMap的一个内部类,是真正存放数据的类
6 private static final Integer CAPACITY = 8;// hashMap初始长度
7 private int size;//集合元素的个数
8
9 // 存或修改元素
10 public void put(K k, V v) {
11 //如果是第一次存放,就初始化数组
12 if (table == null) {
13 inflate();
14 }
15 // 存entry
16 // 根据k的值返回一个int类型的hashCode
17 int hashCode = hash(k);
18 // 根据这个hashCode返回一个数组下标,index是在0~table.length之间的数,不会数组越界
19 int index = indexOf(hashCode);
20 // 如果放入的k已存在,那么将参数k赋值个原先存在的元素,参数v赋值给该元素,达到更新的目的
21 boolean flag = true;
22 for (Entry<K, V> entry = table[index]; entry != null; entry = entry.next) {
//判断是否存在相同的k
23 if (entry.key.equals(k)) {
24 entry.key = k;
25 entry.value = v;
26 flag = false;
27 }
28 }
29 // 如果存在相同的k就不再执行添加方法
30 if (flag) {
31 addEntry(k, v, index);
32 }
33
34 }
35
36 // 取
37 public V get(K k) {
38 // 根据k的值返回一个hashCode
39 int hashCode = hash(k);
40 // 根据这个hashCode返回一个数组下标
41 int index = indexOf(hashCode);
42 // 根据传入的k计算出table数组的下标index,然后循环判断这个index位置是否存在这个k,如果存在就返回该entry的value,如果不存在就返回null
43 for (Entry<K, V> entry = table[index]; table[index] != null; entry = entry.next) {
44 if (entry.key.equals(k)) {
45 return entry.value;
46 }
47 }
48
49 return null;
50 }
51 //添加方法,把最新添加的entry元素放进table数组index位置,把原先在index位置的元素作为新添元素的下一个元素(他的属性)
52 private void addEntry(K k, V v, int index) {
53 Entry<K, V> newEntry = new Entry<>(k, v, table[index]);
54 table[index] = newEntry;
55 // 每存入一个元素数组的元素个数就加一
56 size++;
57
58 }
59
60 private int indexOf(int hashCode) {
61 //用得到的hashCode值对数组长度取模,保证不会现数组越界的错误
62 return hashCode % table.length;
63 }
64 //返回k值的hashcode值
65 private int hash(K k) {
66
67 return k.hashCode();
68 }
69 //初始化table数组
70 private void inflate() {
71 table = new Entry[CAPACITY];
72
73 }
74 //内部类,存储数据的实体
75 class Entry<K, V> {
76 private K key;
77 private V value;
78 private Entry<K, V> next;
79
80 public Entry(K key, V value) {
81 82 this.key = key;
83 this.value = value;
84 }
85
86 public Entry(K key, V value, Entry<K, V> next) {
87 88 this.key = key;
89 this.value = value;
90 this.next = next;
91 }100
101 }
102 //测试
103 public static void main(String[] args) {
104 MyHashMap<String, String> myHashMap = new MyHashMap<>();
105 myHashMap.put("1", "1p");
106 myHashMap.put("1", "1pp");
107 myHashMap.put("2", "2p");
108 System.out.println(myHashMap.get("1"));//1pp,out()方法即是存放又是修改
109 System.out.println(myHashMap.size);//2
110 }
111
112 }