目錄
一.認(rèn)識(shí)哈希表:
1.1什么是哈希表?
1.2哈希表的表示:?
1.3常見(jiàn)哈希函數(shù):
?二.認(rèn)識(shí)HashMap和HashSet:
2.1關(guān)于Map.Entry的說(shuō)明:,>
2.2Map常用方法說(shuō)明:
2.3HashMap的使用案例:
2.4Set常見(jiàn)方法說(shuō)明:
?2.5HashSet使用案例:
源碼:
一.認(rèn)識(shí)哈希表:
1.1什么是哈希表?
之前的學(xué)習(xí)中,如果我們要查找一個(gè)元素,肯定是要經(jīng)過(guò)比較的,那有沒(méi)有一種辦法,可以不用經(jīng)過(guò)比較,直接就能拿到呢?
如果我們能構(gòu)造一種存儲(chǔ)結(jié)構(gòu),通過(guò)一種函數(shù) (hashFunc) 使元素的存儲(chǔ)位置與函數(shù)得出的關(guān)鍵碼之間能夠建立一一映射的關(guān)系,那么在查找某個(gè)元素的時(shí)候,就能通過(guò)這個(gè)函數(shù)來(lái)很快的找到該元素所在的位置。
這種函數(shù)就叫做哈希(散列)函數(shù),上述所說(shuō)構(gòu)造出來(lái)的結(jié)構(gòu),叫做哈希表或者稱為散列表。
?哈希表簡(jiǎn)介:
哈希表(Hash Table):也叫做散列表。是根據(jù)關(guān)鍵碼值(Key Value)直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。哈希表通過(guò)「鍵 key 」和「映射函數(shù) Hash(key) 」計(jì)算出對(duì)應(yīng)的「值 value」,把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄,以加快查找的速度。這個(gè)映射函數(shù)叫做「哈希函數(shù)(散列函數(shù))」,存放記錄的數(shù)組叫做「哈希表(散列表)」。
1.2哈希表的表示:?
?舉個(gè)栗子:為了記錄一個(gè)班的學(xué)生的信息,分別包括學(xué)號(hào)和姓名。我們就可以用哈希表(數(shù)組加鏈表)來(lái)記錄,這里學(xué)號(hào)(關(guān)鍵值key)通過(guò)哈希函數(shù)得到一個(gè)數(shù)組下標(biāo),這個(gè)下標(biāo)就是這個(gè)學(xué)生信息存放在對(duì)應(yīng)數(shù)組中的位置,同時(shí)學(xué)生的信息(姓名和學(xué)號(hào))叫做鍵值對(duì),又稱作Entry
?使用方法:
- 向哈希表中插入一個(gè)關(guān)鍵碼值:哈希函數(shù)決定該關(guān)鍵字的對(duì)應(yīng)值應(yīng)該存放到表中的哪個(gè)區(qū)塊,并將對(duì)應(yīng)值存放到該區(qū)塊中。
- 在哈希表中搜索一個(gè)關(guān)鍵碼值:使用相同的哈希函數(shù)從哈希表中查找對(duì)應(yīng)的區(qū)塊,并在特定的區(qū)塊搜索該關(guān)鍵字對(duì)應(yīng)的值。
- 實(shí)現(xiàn)哈希表: 數(shù)組+鏈表 或者 ?數(shù)組+二叉樹(shù)
1.3常見(jiàn)哈希函數(shù):
- 直接定值法--(常用):取關(guān)鍵字的某個(gè)線性函數(shù)為散列地址:Hash(Key)= A*Key + B 優(yōu)點(diǎn):簡(jiǎn)單、均勻 缺點(diǎn):需要事先知道關(guān) 鍵字的分布情況 使用場(chǎng)景:適合查找比較小且連續(xù)的情況
- . 除留余數(shù)法--(常用) :?
設(shè)散列表中允許的 地址數(shù)為 m ,取一個(gè)不大于 m ,但最接近或者等于 m 的質(zhì)數(shù) p 作為除數(shù),按照哈希函數(shù): Hash(key) = key% p(p<=m), 將關(guān)鍵碼轉(zhuǎn)換成哈希地址 例如:![]()
?二.認(rèn)識(shí)HashMap和HashSet:
?HashMap和HashSet是Java集合框架中的兩個(gè)常用類,它們都實(shí)現(xiàn)了Set接口,但在實(shí)現(xiàn)原理和用途上有一些區(qū)別。
- HashMap:HashMap是基于哈希表的實(shí)現(xiàn),它使用鍵值對(duì)(key-value)的方式存儲(chǔ)數(shù)據(jù)。HashMap允許存儲(chǔ)null鍵和null值,并且可以存儲(chǔ)重復(fù)的值,但不允許重復(fù)的鍵。HashMap內(nèi)部使用哈希函數(shù)將鍵映射到哈希表的索引位置,以實(shí)現(xiàn)快速的插入、刪除和查找操作。HashMap的查找操作是通過(guò)鍵來(lái)進(jìn)行的,因此可以根據(jù)鍵快速地獲取對(duì)應(yīng)的值。
- HashSet:HashSet也是基于哈希表的實(shí)現(xiàn),它存儲(chǔ)唯一的元素,不允許重復(fù)值。HashSet允許存儲(chǔ)null值,但只能存儲(chǔ)一個(gè)null元素。HashSet內(nèi)部使用哈希函數(shù)將元素映射到哈希表的索引位置,以實(shí)現(xiàn)快速的插入、刪除和查找操作。HashSet的查找操作是通過(guò)元素來(lái)進(jìn)行的,因此可以根據(jù)元素快速地判斷是否存在于集合中。
2.1關(guān)于Map.Entry<K, V>的說(shuō)明:
方法 | 解釋 |
K
getKey
()
|
返回
entry
中的
key
|
V
getValue
()
|
返回
entry
中的
value
|
V setValue(V value)
|
將鍵值對(duì)中的
value
替換為指定
value
|
2.2Map常用方法說(shuō)明:
2.3HashMap的使用案例:
基礎(chǔ)操作:
Map<String, String> m = new HashMap<>();
// put(key, value):插入key-value的鍵值對(duì)
// 如果key不存在,會(huì)將key-value的鍵值對(duì)插入到map中,返回null
m.put("林沖", "豹子頭");
m.put("魯智深", "花和尚");
m.put("武松", "行者");
m.put("宋江", "及時(shí)雨");
String str = m.put("李逵", "黑旋風(fēng)");
m.remove("武松","行者");
System.out.println("map的大?。╯ize):" + m.size());
System.out.println("map中的元素:" + m);
System.out.println("這時(shí)str為空: " + str);// put(key,value): 注意key不能為空,但是value可以為空
m.put("無(wú)名", null); // key如果為空,會(huì)拋出空指針異常
System.out.println("當(dāng)前map的大?。?" + m.size());
str = m.put("李逵", "鐵牛");
System.out.println("返回舊的value值: " + str);
System.out.println("得到Key所對(duì)應(yīng)的value值: " + m.get("李逵"));
運(yùn)行結(jié)果:
GetOrDefault()和containKey(key):
//GetOrDefault(): 如果key存在,返回與key所對(duì)應(yīng)的value,如果key不存在,返回一個(gè)默認(rèn)值
System.out.println("=========================================");
System.out.println("李逵存在,返回key對(duì)應(yīng)的value: " + m.getOrDefault("李逵", "牛牛"));
System.out.println("史進(jìn)不存在,返回一個(gè)默認(rèn)值: " + m.getOrDefault("史進(jìn)", "九龍紋"));
System.out.println("=========================================");
//containKey(key):檢測(cè)key是否包含在Map中,時(shí)間復(fù)雜度:O(logN)
System.out.println(m.containsValue("豹子頭"));
System.out.println(m.containsValue("行者"));
運(yùn)行結(jié)果:
三種遍歷方法:
System.out.println("-----key ------value -----Entry的遍歷方法:----------");
System.out.println("key遍歷: ");
for (String s : m.keySet()) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("value遍歷: ");
for (String s : m.values()) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("entry遍歷: ");
for (Map.Entry<String, String> entry : m.entrySet()) {
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
運(yùn)行結(jié)果:
注意:
1. Map 是一個(gè)接口,不能直接實(shí)例化對(duì)象 ,如果 要實(shí)例化對(duì)象只能實(shí)例化其實(shí)現(xiàn)類 TreeMap 或者 HashMap2. Map 中存放鍵值對(duì)的 Key 是唯一的, value 是可以重復(fù)的3. Map 中的 Key 可以全部分離出來(lái),存儲(chǔ)到 Set 中 來(lái)進(jìn)行訪問(wèn) ( 因?yàn)?/span> Key 不能重復(fù) ) 。4. Map 中的 value 可以全部分離出來(lái),存儲(chǔ)在 Collection 的任何一個(gè)子集合中 (value 可能有重復(fù) ) 。5. Map 中鍵值對(duì)的 Key 不能直接修改, value 可以修改,如果要修改 key ,只能先將該 key 刪除掉,然后再來(lái)進(jìn)行重新插入。
2.4Set常見(jiàn)方法說(shuō)明:
方法 | 解釋 |
boolean
add
(E e)
|
添加元素,但重復(fù)元素不會(huì)被添加成功
|
void
clear
()
|
清空集合
|
boolean
contains
(Object o)
|
判斷
o
是否在集合中
|
Iterator<E>
iterator
()
|
返回迭代器
|
boolean
remove
(Object o)
|
刪除集合中的
o
|
int size()
|
返回set中元素的個(gè)數(shù) |
boolean isEmpty()
|
檢測(cè)
set
是否為空,空返回
true
,否則返回
false
|
Object[] toArray()
|
將
set
中的元素轉(zhuǎn)換為數(shù)組返回
|
boolean containsAll(Collection<?> c)
|
集合
c
中的元素是否在
set
中全部存在,是返回
true
,否則返回
false
|
boolean addAll(Collection<? extends
E> c)
|
將集合
c
中的元素添加到
set
中,可以達(dá)到去重的效果
|
?2.5HashSet使用案例:
System.out.println("================HashSet===============");
Set<String> s = new HashSet<>();
boolean isIn = s.add("apple");
s.add("orange");
s.add("peach");
s.add("banana");
System.out.println(s.size());
System.out.println(s);
System.out.println("add(key): 如果key不存在,則插入,返回true: " + isIn);
isIn = s.add("apple");
System.out.println("add(key):如果key存在,則返回false: " + isIn);
// contains(key): 如果key存在,返回true,否則返回false
System.out.println(s.contains("apple"));
System.out.println(s.contains("watermelen"));
s.remove("apple");// remove(key): key存在,刪除成功返回true
System.out.println(s);// key不存在,刪除失敗返回false , key為空,
System.out.println("迭代器遍歷:");
Iterator<String> it = s.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
運(yùn)行結(jié)果:
注意:
1. Set 是繼承自Collection的一個(gè)接口類2. Set 中只存儲(chǔ)了 key ,并且要求 key 一定要唯一3. Set 的底層是使用 Map 來(lái)實(shí)現(xiàn)的,其使用 key 與 Object 的一個(gè)默認(rèn)對(duì)象作為鍵值對(duì)插入到 Map 中的4. 實(shí)現(xiàn) Set 接口的常用類有 TreeSet 和 HashSet ,還有一個(gè) LinkedHashSet , LinkedHashSet 是在 HashSet 的基礎(chǔ)上維護(hù)了一個(gè)雙向鏈表來(lái)記錄元素的插入次序。5. Set 中的Key不能修改,如果要修改,先將原來(lái)的刪除掉,然后再重新插入6. Set 中不能插入null的key
源碼:
import java.util.TreeMap;
import java.util.Set;
import java.util.Map;
public class Test1 {
public static void main(String[] args) {
Map<String, String> m = new HashMap<>();
// put(key, value):插入key-value的鍵值對(duì)
// 如果key不存在,會(huì)將key-value的鍵值對(duì)插入到map中,返回null
m.put("林沖", "豹子頭");
m.put("魯智深", "花和尚");
m.put("武松", "行者");
m.put("宋江", "及時(shí)雨");
String str = m.put("李逵", "黑旋風(fēng)");
m.remove("武松","行者");
System.out.println("map的大?。╯ize):" + m.size());
System.out.println("map中的元素:" + m);
System.out.println("這時(shí)str為空: " + str);// put(key,value): 注意key不能為空,但是value可以為空
m.put("無(wú)名", null); // key如果為空,會(huì)拋出空指針異常
System.out.println("當(dāng)前map的大?。?" + m.size());
str = m.put("李逵", "鐵牛");
System.out.println("返回舊的value值: " + str);
System.out.println("得到Key所對(duì)應(yīng)的value值: " + m.get("李逵"));
//GetOrDefault(): 如果key存在,返回與key所對(duì)應(yīng)的value,如果key不存在,返回一個(gè)默認(rèn)值
System.out.println("=========================================");
System.out.println("李逵存在,返回key對(duì)應(yīng)的value: " + m.getOrDefault("李逵", "牛牛"));
System.out.println("史進(jìn)不存在,返回一個(gè)默認(rèn)值: " + m.getOrDefault("史進(jìn)", "九龍紋"));
System.out.println("=========================================");
//containKey(key):檢測(cè)key是否包含在Map中,時(shí)間復(fù)雜度:O(logN)
System.out.println(m.containsValue("豹子頭"));
System.out.println(m.containsValue("行者"));
System.out.println("-----key ------value -----Entry的遍歷方法:----------");
System.out.println("key遍歷: ");
for (String s : m.keySet()) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("value遍歷: ");
for (String s : m.values()) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("entry遍歷: ");
for (Map.Entry<String, String> entry : m.entrySet()) {
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
System.out.println("================HashSet===============");
Set<String> s = new HashSet<>();
boolean isIn = s.add("apple");
s.add("orange");
s.add("peach");
s.add("banana");
System.out.println(s.size());
System.out.println(s);
System.out.println("add(key): 如果key不存在,則插入,返回true: " + isIn);
isIn = s.add("apple");
System.out.println("add(key):如果key存在,則返回false: " + isIn);
// contains(key): 如果key存在,返回true,否則返回false
System.out.println(s.contains("apple"));
System.out.println(s.contains("watermelen"));
s.remove("apple");// remove(key): key存在,刪除成功返回true
System.out.println(s);// key不存在,刪除失敗返回false , key為空,
System.out.println("迭代器遍歷:");
Iterator<String> it = s.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
}
}
結(jié)語(yǔ):?寫博客不僅僅是為了分享學(xué)習(xí)經(jīng)歷,同時(shí)這也有利于我鞏固自己的知識(shí)點(diǎn),總結(jié)該知識(shí)點(diǎn),由于作者水平有限,對(duì)文章有任何問(wèn)題的還請(qǐng)指出,接受大家的批評(píng),讓我改進(jìn)。同時(shí)也希望讀者們不吝嗇你們的點(diǎn)贊+收藏+關(guān)注,你們的鼓勵(lì)是我創(chuàng)作的最大動(dòng)力!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-839803.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-839803.html
到了這里,關(guān)于【java數(shù)據(jù)結(jié)構(gòu)】HashMap和HashSet的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!