- 這里再補充幾個手撕HashMap的方法
1、remove()
- remove 方法引數值應該是鍵值對的鍵的值,當傳入鍵值對的鍵的時候,remove 方法會洗掉對應的鍵值對
- 需要利用我們自己先前創建的 hashcodeList 來實作,hashcodeList 存入了所有被使用的 hashcode 值,方便后續的操作
- 在 put() 中,當添加新的鍵值對時,就會呼叫
hashcodeList.add(hashcode);來存入添加的 hashcode 值 - hashcodeList:
/**
* 不需要遍歷陣列,大大減少了代碼量,直接存入hashcode的值
* 用來記錄被使用的hashcode,方便后續其他方法的操作
*/
List<Integer> hashcodeList = new ArrayList<>();
- remove() 方法的思路:
- 根據傳入的 key 的值,遍歷 hashmap
- 當 key 的值相同時,洗掉它,與此同時遍歷 hashcodeList
- 當 hashcodeList 中存盤的哈希值與 key 通過 hashcode(key) 方法后得到的哈希值相等時,洗掉這個 hashcodeList 值
- 代碼:
/**
* 洗掉傳入的key值所對應的鍵值對物件
*
* @param key 傳入的key
*/
@Override
public void remove(K key) {
int hashcode = hashcode(key);
for (Entry<K, V> entry : mapArr[hashcode]
) {
//要把hashcodeList中的hashcode洗掉
hashcodeList.removeIf(integer -> hashcode(entry.getKey()) == integer);
//洗掉 mapArr
if (entry.getKey().equals(key)) {
mapArr[hashcode].remove();
}
}
}
2、clear()
- clear 方法呼叫之后,會清除 hashmap 中所有的關聯或映射,即清除所有的 key、value
- 思路:
- hashcodeList 中存盤的是使用過的哈希值,而 mapArr 的下標是對應的哈希值,存盤的是對應的value值
- 遍歷 hashcodeList,將里面的值一個個取出來并放到 mapArr 的下標,一一呼叫 remove 方法
/**
* 清除 HashMap 中的所有關聯或者映射
*/
@Override
public void clear() {
for (int i = 0; i < hashcodeList.size(); i++) {
for (Entry<K, V> entry : mapArr[hashcodeList.get(i)]
) {
mapArr[hashcodeList.get(i)].remove();
//同時要把hashcodeList中的hashcode清除
hashcodeList.clear();
}
}
}
3、containsKey()
- 傳入一個 key 的值,判斷是否存在這個鍵所對應的鍵值對,存在則回傳 true,不存在則回傳 false
- 思路:
- 先生成傳入 key 的對應的哈希值
- 判斷下標為這個哈希值的陣列是否為空,為空則直接回傳 false
- 如果不為空,則遍歷這個陣列找到相同的 key 則回傳 true,否則回傳 false
- 會出現陣列下標越界,如果出現,則說明不存在這個下標,自然也不存在這個哈希值,所以可以用 try、catch 環繞直接回傳false
/**
* 判斷是否存在key值所對應的映射,回傳一個布林值
*
* @param key 傳入一個key的值
* @return 判斷是否存在key值所對應的映射,回傳一個布林值
*/
@Override
public boolean containsKey(K key) {
int hashcode = hashcode(key);
try {
//如果發現沒存過,直接回傳false
if (null == mapArr[hashcode]) {
return false;
} else {
//如果遍歷能查找到key,則回傳true
//如果遍歷不能找到,則回傳null
for (Entry<K, V> entry : mapArr[hashcode]
) {
if (entry.getKey().equals(key)) {
return true;
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
//只要出現陣列下標越界就說明沒找到,直接回傳false
return false;
}
return false;
}
4、keySet()
- 作用很簡單,回傳一個集合,集合包含了所有的 key 的值
- 注意:是 key 的值,而不是哈希值
- 思路:
- 當 hashcodeList 為空時,說明沒有哈希值,自然也不存在 key,所以直接回傳 null
- 否則遍歷 mapArr 陣列,下標為 hashcodeList 存盤的哈希值,用 getKey 取出 key
/**
* 獲取HashMap的鍵的集合,以Set<K>保存
*
* @return 回傳key的集合
*/
@Override
public Set<K> keySet() {
//若沒有hashcode值,直接回傳空
if (null == hashcodeList) {
return null;
} else {
Set<K> kSet = new HashSet<>();
for (int i = 0; i < hashcodeList.size(); i++) {
//遍歷 mapArr
for (Entry<K, V> entry : mapArr[hashcodeList.get(i)]
) {
kSet.add(entry.getKey());
}
}
return kSet;
}
}
5、values()
- 與 keySet 類似,作用是回傳一個集合,其中包含了所有的 value 值
- 思路:
- 當 hashcodeList 為空時,說明沒有哈希值,自然也不存在 key,自然也不存在 value,所以直接回傳 null
- 否則遍歷 mapArr 陣列,下標為 hashcodeList 存盤的哈希值,用 getValue 取出 value
/**
* 獲取HashMap中value的集合
*
* @return 回傳value集合
*/
@Override
public Collection<V> values() {
//如果沒有hashcode值,則直接回傳空
if (null == hashcodeList) {
return null;
} else {
//生成一個集合
Collection<V> vCollection = new ArrayList<>();
for (int i = 0; i < hashcodeList.size(); i++) {
//遍歷 mapArr
for (Entry<K, V> entry : mapArr[hashcodeList.get(i)]
) {
vCollection.add(entry.getValue());
}
}
return vCollection;
}
}
6、entrySet()
- 回傳一個集合,包含了所有的鍵值對及其映射關系
- 思路:
- 當 hashcodeList 為空時,說明沒有哈希值,自然也不存在 key,自然也不存在 value,所以直接回傳 null
- 否則遍歷 mapArr 陣列,下標為 hashcodeList 存的哈希值,直接呼叫 add 方法添加
/**
* 得到 HashMap 中各個鍵值對映射關系的集合
*
* @return 回傳一個映射關系的集合
*/
@Override
public Set<Entry<K, V>> entrySet() {
//若沒有hashcode值,直接回傳空
if (null == hashcodeList) {
return null;
} else {
Set<Entry<K, V>> entrySet = new HashSet<>();
for (int i = 0; i < hashcodeList.size(); i++) {
//遍歷 mapArr
for (Entry<K, V> entry : mapArr[hashcodeList.get(i)]
) {
entrySet.add(entry);
}
}
return entrySet;
}
}
7、size()
- size 方法就是回傳一個 int 值,是 hashmap 的鍵值對的數量
- 思路:很簡單,遍歷 hashcodeList,存在一個哈希值就說明存在一對鍵值對,直接加一即可
/**
* 得到 HashMap 鍵值對的數量
*
* @return 一個int型整數
*/
@Override
public int size() {
int count = 0;
for (int i = 0; i < hashcodeList.size(); i++) {
count++;
}
return count;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/549035.html
標籤:其他
