基于Java的HashMap和HashSet实现

一、Map接口类:

 1 import java.util.Iterator;
 2 
 3 public interface IMap<K, V> {
 4     /* 清除所有键值对 */
 5     void clear();
 6 
 7     /* key是否已经存在 */
 8     boolean containsKey(K key);
 9 
10     /* value是否存在 */
11     boolean containsValue(V value);
12 
13     /* 根据key获得value */
14     V get(K key);
15 
16     /* map是否为空 */
17     boolean isEmpty();
18 
19     /* 所有key组成的数组 */
20     MyHashSet<K> keySet();
21 
22     /* 存入键值对 */
23     void put(K key, V value);
24 
25     /* 把另外一个map中的所有键值对存入到当前map中 */
26     void putAll(IMap<? extends K, ? extends V> map);
27 
28     /* 根据key删除一个键值对 */
29     V remove(K key);
30 
31     /* 键值对的个数 */
32     int size();
33 
34     /* 所有的value组成的数组 */
35     V[] values();
36 
37     Iterator<MyHashMap.Node> iterator();
38 }
View Code

二、HashSet接口类:

 1 import java.util.Iterator;
 2 
 3 public interface IHashSet<E> {
 4     void add(E key);
 5 
 6     void remove(E key);
 7 
 8     void clear();
 9 
10     boolean contains(E key);
11 
12     boolean isEmpty();
13 
14     int size();
15 
16     Iterator<E> iterator();
17 }
View Code

三、HashMap类:

  1 import java.util.Iterator;
  2 
  3 public class MyHashMap<K, V> implements IMap<K, V> {
  4     private int length = 16;
  5 
  6     private Node[] buckets = new Node[length];//
  7     private int size;
  8 
  9     @Override
 10     public void clear() {
 11         for (int i = 0; i < buckets.length; i++) {
 12             buckets[i] = null;
 13         }
 14     }
 15 
 16     @Override
 17     public boolean containsKey(K key) {
 18         int index = hash1(key);
 19         if (buckets[index] == null) {
 20             return false;
 21         } else {
 22             Node<K, V> p = buckets[index];// 相当于在链表中找key
 23             while (p != null) {
 24                 K k1 = p.key;
 25                 // Java == 比较的是地址
 26                 // 借用java机制,hashcode和equals都来自于Object,用户可以改写这两个方法——制定对象相等的规则
 27                 if (k1 == key || (k1.hashCode() == key.hashCode() && k1.equals(key))) {
 28                     return true;
 29                 }
 30                 p = p.next;
 31             }
 32         }
 33 
 34         return false;
 35     }
 36 
 37     @Override
 38     public boolean containsValue(V value) {
 39         for (int i = 0; i < buckets.length; i++) {
 40             if (buckets[i] != null) {
 41                 Node<K, V> p = buckets[i];
 42                 while (p != null) {
 43                     if (p.value.equals(value))
 44                         return true;
 45                 }
 46             }
 47         }
 48         return false;
 49     }
 50 
 51     @Override
 52     public V get(K key) {
 53         int index = hash1(key);
 54         if (buckets[index] == null) {
 55             return null;
 56         } else {
 57             Node<K, V> p = buckets[index];
 58             while (p != null) {
 59                 K k1 = p.key;
 60                 if (k1 == key || (k1.hashCode() == key.hashCode() && k1.equals(key))) {
 61                     return p.value;
 62                 }
 63                 p = p.next;
 64             }
 65         }
 66         return null;
 67     }
 68 
 69     @Override
 70     public boolean isEmpty() {
 71         return size == 0;
 72     }
 73 
 74     @Override
 75     public MyHashSet<K> keySet() {
 76         MyHashSet<K> set = new MyHashSet<>();
 77         for (int i = 0; i < buckets.length; i++) {
 78             if (buckets[i] != null) {
 79                 Node<K, V> p = buckets[i];
 80                 while (p != null) {
 81                     set.add(p.key);
 82                     p = p.next;
 83                 }
 84             }
 85         }
 86         return set;
 87     }
 88 
 89     @Override
 90     public void put(K key, V value) {
 91         Node<K, V> node = new Node<>(key, value);
 92         int index = hash1(key);// 算出在桶中的位置
 93         if (buckets[index] == null) {// 桶中没有东西
 94             buckets[index] = node;
 95             size++;
 96         } else {
 97             Node<K, V> p = buckets[index];// 链表的表头找到
 98             while (p != null) {
 99                 K k1 = p.key;
100                 if (key == k1 || key.hashCode() == k1.hashCode() && key.equals(k1)) {
101                     p.value = value;// 存在相同的key,则更新value
102                     break;
103                 }
104                 if (p.next == null) {
105                     p.next = node;
106                     size++;
107                     break;
108                 }
109                 p = p.next;
110             }
111 
112         }
113     }
114 
115     private int hash1(K key) {
116         // return key.hashCode() % length;
117         int h = 0;
118         int seed = 31;// 素数
119         String s = key.toString();
120         for (int i = 0; i != s.length(); ++i) {
121             h = seed * h + s.charAt(i);
122         }
123         return h % length;
124     }
125 
126     @Override
127     public void putAll(IMap<? extends K, ? extends V> map) {
128 
129     }
130 
131     @Override
132     public V remove(K key) {
133         int index = hash1(key);// 先定桶的位置
134         if (buckets[index] == null) {
135             return null;
136         } else {
137             Node<K, V> p = buckets[index];// 找到表头
138             Node<K, V> pre = p;
139 
140             while (p != null) {
141                 K k1 = p.key;
142                 if (k1.hashCode() == key.hashCode() && k1.equals(key)) {
143                     // 移除
144                     if (p == pre) {
145                         buckets[index] = pre.next;
146                     } else {
147                         pre.next = p.next;
148                     }
149                     size--;
150                     return p.value;
151                 }
152                 pre = p;
153                 p = p.next;
154             }
155         }
156         return null;
157     }
158 
159     @Override
160     public int size() {
161         return size;
162     }
163 
164     @Override
165     public V[] values() {
166         return null;
167     }
168 
169     private class MapInterator implements Iterator<Node> {
170         int i = 0;
171         Node p = buckets[0];
172 
173         @Override
174         public boolean hasNext() {
175             while (this.i < length && p == null) {
176                 this.i++;
177                 if (this.i == length)
178                     p = null;
179                 else
180                     p = buckets[this.i];
181             }
182             // i是一个非空的桶,p是链表头
183             return p != null;
184         }
185 
186         @Override
187         public Node next() {
188             Node res = p;
189             p = p.next;
190             return res;
191         }
192     }
193 
194     @Override
195     public Iterator<Node> iterator() {
196         return new MapInterator();
197     }
198 
199     @Override
200     public String toString() {
201         StringBuilder sb = new StringBuilder();
202         for (int i = 0; i < buckets.length; i++) {
203             if (buckets[i] != null) {
204                 Node<K, V> p = buckets[i];
205                 while (p != null) {
206                     sb.append("(" + p.key + "," + p.value + "),");
207                     p = p.next;
208                 }
209             }
210         }
211         return sb.toString();
212     }
213 
214     public class Node<K, V> {
215         public K key;
216         public V value;
217 
218         public Node(K key, V value) {
219             this.key = key;
220             this.value = value;
221         }
222 
223         private Node next;
224 
225         @Override
226         public String toString() {
227             return "BSTNode{" + "key=" + key + ", value=" + value + '}';
228         }
229     }
230 }
View Code

四、HashSet类:

 1 import java.util.Iterator;
 2 
 3 public class MyHashSet<E> implements IHashSet<E> {
 4     private MyHashMap<E, E> map = new MyHashMap<>();
 5 
 6     @Override
 7     public void add(E key) {
 8         map.put(key, null);
 9     }
10 
11     @Override
12     public void remove(E key) {
13         map.remove(key);
14     }
15 
16     @Override
17     public void clear() {
18         map.clear();
19     }
20 
21     @Override
22     public boolean contains(E key) {
23         return map.containsKey(key);
24     }
25 
26     @Override
27     public boolean isEmpty() {
28         return map.isEmpty();
29     }
30 
31     @Override
32     public int size() {
33         return map.size();
34     }
35 
36     @Override
37     public Iterator<E> iterator() {
38         Iterator<MyHashMap.Node> iter = map.iterator();
39         return new Iterator<E>() {
40             @Override
41             public boolean hasNext() {
42                 return iter.hasNext();
43             }
44 
45             @Override
46             public E next() {
47                 return (E) iter.next().key;
48             }
49         };
50     }
51 
52     @Override
53     public String toString() {
54         Iterator<MyHashMap.Node> iterator = map.iterator();
55         StringBuilder sb = new StringBuilder();
56         while (iterator.hasNext()) {
57             sb.append(iterator.next().key + ",");
58         }
59         return sb.toString();
60     }
61 }
View Code

五、HashMap优化:

  1、扩容:如果当表中的75%已经被占用,即视为需要扩容了。

  2、如果冲突造成的链表长度超过8的时候,就要转为红黑树存储。

  3、hash函数优化。h = key.hashCode(); h^(h>>16); h % length。

猜你喜欢

转载自www.cnblogs.com/xiaoyh/p/10389610.html