Java數(shù)據(jù)存儲(chǔ)的“雙子星”對(duì)決(Map和Set的區(qū)別)
??一、搜索
??1.概念
搜索:是指在數(shù)據(jù)集合過程中查找特定元素或滿足特定條件元素的過程。如:在一組數(shù)組中查找特定的數(shù)字。常見的搜索有直接遍歷和二分查找.....
直接遍歷和二分查找比較適合靜態(tài)類型的查找,即一般不會(huì)對(duì)區(qū)間進(jìn)行插入和刪除操作。
所以當(dāng)需要?jiǎng)討B(tài)查找時(shí),即查找時(shí)要進(jìn)行一些插入和刪除,上述的方法并不適用 。如:在學(xué)生系統(tǒng)中,快速查找學(xué)生的成績(jī)、統(tǒng)計(jì)單詞出現(xiàn)的次數(shù)、確保用戶名唯一(去重)。
Map和Set是一種專門用來進(jìn)行搜索的容器或者數(shù)據(jù)結(jié)構(gòu),是一種適合動(dòng)態(tài)查找的集合容器。
??2.模型
一般把搜索的數(shù)據(jù)稱為關(guān)鍵字(key),和關(guān)鍵字對(duì)應(yīng)的稱為值(value),所以有兩種模型:
- 1.純key模型:由唯一的鍵(key)組成,沒有與鍵直接關(guān)聯(lián)的特定值(value)。
特點(diǎn):重點(diǎn)在于對(duì)鍵的管理和操作,常用于判斷某個(gè)元素是否存在。
應(yīng)用場(chǎng)景:數(shù)據(jù)去重,黑名單過濾等......
- 2.key-value模型:是一種鍵(key)和值(value)進(jìn)行相關(guān)聯(lián)的數(shù)據(jù)組織形式。每個(gè)鍵都對(duì)應(yīng)著一個(gè)特定的值,通過鍵可以快速查找、更新與之關(guān)聯(lián)的值。如查找在一串字符串中查找,某個(gè)單詞在該字符串中出現(xiàn)的次數(shù)。
特點(diǎn):鍵是唯一的,用于快速定位和訪問對(duì)應(yīng)的值,其值可以是各種類型的數(shù)據(jù)。
應(yīng)用場(chǎng)景:廣泛應(yīng)用于配置文件、數(shù)據(jù)庫(kù)等,比如,以用戶ID為鍵,存儲(chǔ)用戶姓名等為值。
Set只存儲(chǔ)了key,Map存儲(chǔ)的就是key—value的鍵對(duì)值。
??二、Map
??1.什么是Map?
Map是接口類,該類沒有繼承Collection,儲(chǔ)存的是<K,V>結(jié)構(gòu)的鍵值對(duì),并且K一定是唯一的,不能重復(fù)。
??2.Map的實(shí)例化
Map<K,V>是將鍵(key)與值(value)進(jìn)行關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),K代表鍵的類型,V代表值的類型。

Map的實(shí)現(xiàn)類主要有HashMap,TreeMap
實(shí)例化的實(shí)現(xiàn):
public static void main(String[] args) {
Map<String,Integer> map1=new HashMap<>();
Map<String,Integer> map2=new TreeMap<>();
}Map是一個(gè)接口,不能直接實(shí)例化對(duì)象,如果要實(shí)例化對(duì)象只能通過其實(shí)現(xiàn)類TreeMap或者HashMap來實(shí)現(xiàn)
??3.Map的常見方法
| 方法 | 解釋 |
| V put(K key,V value) | 設(shè)置key值與value值相關(guān)聯(lián) |
| V remove(Object key) | 將key對(duì)應(yīng)的映射關(guān)系刪除 |
| V remove(Object key,Object value) | 只有指定的鍵與指定的值相匹配時(shí)才可以刪除 |
| V get(Object key) | 返回key對(duì)應(yīng)的value值 |
| V getOrDefault(Object key,V defalutValue) | 返回key對(duì)應(yīng)的value,key不存在,返回默認(rèn)值 |
Set<K> keySet() | 返回key中的不重復(fù)集合 |
Collection<V> values() | 返回value的可重復(fù)集合 |
| Set<Map.Entry<K,V>> entrySet() | 返回所有的key-value的映射關(guān)系 |
| boolean containsKey(Object key) | 判斷是否包含key |
| boolean containsValue(Object value) | 判斷是否包含value |
??4.Map方法的使用
public static void main(String[] args) {
Map<String,Integer> map=new HashMap<>();
//map:設(shè)置k,v值
map.put("a",2);
map.put("c",5);
map.put("s",21);
//get:獲取key對(duì)應(yīng)的value值
System.out.println(map.get("a"));//2
System.out.println(map.get("b"));//不存在key值,其默認(rèn)值為null
//getOrDefault:
//如果map中有key值,返回key對(duì)應(yīng)的value1值,否則返回設(shè)置的默認(rèn)值
System.out.println(map.getOrDefault("a",1));//2
System.out.println(map.getOrDefault("b",3));//3
//remove1:如果key值與指定的值相匹配,刪除;否則,不刪除
map.remove("a",1);//不匹配不刪除
System.out.println(map.get("a"));//a對(duì)應(yīng)的value還是2
//remove2:刪除key對(duì)應(yīng)的value值
map.remove("a");
System.out.println(map.get("a"));//null
//containsKey:判斷是否包含key
System.out.println(map.containsKey("c"));//true
//containsValue:判斷是否包含value值
System.out.println(map.containsValue(10));//false
Map<String,Integer> map1=new TreeMap<>();
map1.put("a",2);
map1.put("a",3);
map1.put("b",3);
map1.put("c",6);
//Set<K> keySet:返回key中不重復(fù)的集合
Set<String> keySet=map1.keySet();
System.out.println(keySet);//[a, b, c]
//Collection<V> values:返回value中可重復(fù)的集合
Collection<Integer> value=map1.values();
System.out.println(value);//[3, 3, 6]
//Set<K,V>> entrySet:返回key-value所有的映射關(guān)系
Set<Map.Entry<String,Integer>> entrySet=map1.entrySet();
System.out.println(entrySet);//[a=3, b=3, c=6]
}注意事項(xiàng):
Map中存放鍵值對(duì)的Key是唯一的,value是可重復(fù)的,當(dāng)put相同的key,不同的value值時(shí),只是將key所對(duì)應(yīng)的value值進(jìn)行替換,以最后存放的value為主;
public static void main(String[] args) {
Map<String,Integer> map=new HashMap<>();
map.put("a",11);
map.put("a",24);
map.put("a",15);
System.out.println(map.get("a"));//15
}在HashMap中存放的key和value可以都為空,在TreeMap中插入鍵對(duì)值時(shí),key不能為空,value可以為空;
HashMap
public static void main(String[] args) {
Map<String,Integer> map1=new HashMap<>();
map1.put("a",null);
map1.get("a");//無異常
map1.put(null,null);
map1.get(null);//無異常
}TreeMap
public static void main(String[] args) {
Map<String,Integer> map1=new TreeMap<>();
map1.put("a",null);
map1.get("a");//無異常
map1.put(null,2);
map1.get(null);//報(bào)錯(cuò)
}
- Map中鍵值對(duì)的key不能直接修改,可以直接修改value值,如果要修改key,只能將key刪除,在進(jìn)行重新插入。
- HashMap和TreeMap是Map的接口實(shí)現(xiàn)類,用于存儲(chǔ)鍵對(duì)值數(shù)據(jù),以下是他們的區(qū)別:
| Map的底層結(jié)構(gòu) | TreeMap | HashMap |
| 底層結(jié)構(gòu) | 紅黑樹 | 哈希表(數(shù)組+鏈表/紅黑樹) |
| 插入/刪除/查找時(shí)間復(fù)雜度 | O(log2N) | O(1) |
| 是否有序 | 關(guān)于Key有序 | 無序 |
| 允許null鍵 | 不允許,需可比較 | 允許null鍵 |
| 線程安全 | 不安全 | 不安全 |
| 插入/刪除/查找區(qū)別 | 需要進(jìn)行元素比較 | 通過哈希函數(shù)計(jì)算哈希地址 |
| 比較與覆寫 | key必須能夠比較,否則會(huì)拋出異常 | 自定義類型需要覆寫equals和hashCode方法 |
| 應(yīng)用場(chǎng)景 | 需要key有序 | 無序有序,需要更高的時(shí)間性能 |
??三、Set
??1.什么是Set?
Set是一個(gè)接口,繼承自Collection接口,有HashSet、TreeSet等實(shí)現(xiàn)類,HashSet基于哈希表實(shí)現(xiàn),不保證元素有序;TreeSet基于紅黑樹實(shí)現(xiàn),會(huì)對(duì)元素進(jìn)行排序。
??2.Set的常見方法
| 方法 | 解釋 |
| boolean add(E e) | 添加元素,但元素重復(fù)不添加 |
| boolean remove(Object o) | 刪除集合中元素o |
| boolean contains(Object o) | 判斷o是否包含在集合中 |
| boolean isEmpty() | 檢測(cè)是否為空,為空返回false,否則返回true |
| void clear() | 清空 |
| Iterator<E> iterator() | 使用迭代器遍歷集合中的對(duì)象 |
| int size() | 返回set中元素個(gè)數(shù) |
| Object[] toArray() | 將set中的元素轉(zhuǎn)換為數(shù)組返回 |
| boolean containsAll(Collection<?>c) | 集合中的元素是否在set中的全部存在,是返回true,否則返回false |
| boolean addAll(Collection<? extend) | 將集合c中的元素添加到set中,可以達(dá)到去重的效果 |
??3.Set方法的使用
public static void main(String[] args) {
public static void main(String[] args) {
Set<Integer> set1=new HashSet<>();
//add:添加元素
set1.add(5);
set1.add(20);
set1.add(15);
set1.add(8);
//remove:移除元素
set1.remove(20);
//是否包含該元素
System.out.println(set1.contains(5));//true
System.out.println(set1.contains(2));//false
//Iterator:遍歷集合
Iterator<Integer> iterator=set1.iterator();
while(iterator.hasNext()){
System.out.print(iterator.next()+" ");//5 8 15
}
System.out.println();
//isEmpty:判斷是否為空
System.out.println(set1.isEmpty());//false:不為空
//size:計(jì)算元素個(gè)數(shù)
System.out.println(set1.size());//3
//toArray:將set中的元素轉(zhuǎn)換為數(shù)組
Integer[] toArray=set1.toArray(new Integer[0]);
for (Integer x:toArray) {
System.out.print(x+" ");//5 8 15
}
System.out.println();
//containsAll:set是否包含指定集合的所有元素
Set<Integer> set2=new HashSet<>();
set2.add(1);
set2.add(2);
set2.add(3);
Set<Integer> set3=new HashSet<>();
set3.add(1);
set3.add(2);
//看set2中是否都包含set3集合中的元素
boolean containsAll=set2.containsAll(set3);
System.out.println(containsAll);//true
//addAll:將集合中的元素添加到set中
Set<Integer> set4=new TreeSet<>();
set4.add(1);
set4.add(5);
set4.add(19);
Set<Integer> set5=new TreeSet<>();
set5.add(2);
set5.add(1);
set5.add(6);
boolean addAll=set4.addAll(set5);
Iterator<Integer> iterator1=set4.iterator();
while(iterator1.hasNext()){
//如果是HashSet那么不自動(dòng)排序,如果是TreeSet就自動(dòng)排序
System.out.print(iterator1.next()+" ");//1 2 5 6 19
}注意:
- Set只存儲(chǔ)了key,并且要求key一定要唯一,其key值不能進(jìn)行修改,如果要進(jìn)行修改需要?jiǎng)h除后再插入。
- Set可以對(duì)集合進(jìn)行去重;
- TreeSet的底層是使用Map來實(shí)現(xiàn)的,其使用key與Object的一個(gè)默認(rèn)對(duì)象作為鍵值對(duì)插入到Map中;
- TreeSet和HashSet的區(qū)別
| Set底層結(jié)構(gòu) | TreeSet | HashSet |
| 底層結(jié)構(gòu) | 紅黑樹 | 哈希表 |
| 插入/刪除/查找時(shí)間復(fù)雜度 | O(log2N) | O(1) |
| 是否有序 | key有序 | 不一定有序 |
| 允許null鍵 | 不允許,需可比較 | 允許null鍵 |
| 線程安全 | 不安全 | 不安全 |
| 插入/刪除/查找區(qū)別 | 按照紅黑樹的特性來進(jìn)行插入和刪除 | 1.先計(jì)算key哈希地址2.然后進(jìn)行插入和刪除 |
| 比較與覆寫 | key必須能夠比較,否則會(huì)拋出ClassCastException異常 | 自定義類型需要覆寫equals和hashCode方法 |
| 應(yīng)用場(chǎng)景 | 需要key有序 | 無關(guān)有序,需要更高的時(shí)間性能 |
??四、Map和Set的區(qū)別
| 區(qū)別 | Map | Set |
| 存儲(chǔ)形式 | 是一種鍵對(duì)值(key-value)集合 | 是值的集合,值存在單一的值,不存在重復(fù)元素 |
| 訪問方式 | get(key)方法 | 沒有鍵對(duì)值的映射,一般通過for循環(huán)或者迭代器遍歷 |
| 唯一性 | 鍵是唯一的,不用重復(fù),值可以重復(fù) | 所有元素都是唯一的 |
| 應(yīng)用場(chǎng)景 | 需要建立映射關(guān)系的場(chǎng)景 | 需要確保元素唯一的場(chǎng)景 |
到此這篇關(guān)于Java數(shù)據(jù)存儲(chǔ)的“雙子星”對(duì)決的文章就介紹到這了,更多相關(guān)Java數(shù)據(jù)存儲(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java GUI圖形界面開發(fā)實(shí)現(xiàn)小型計(jì)算器流程詳解
本文章向大家介紹Java GUI圖形界面開發(fā)實(shí)現(xiàn)小型計(jì)算器,主要包括布局管理器使用實(shí)例、應(yīng)用技巧、基本知識(shí)點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08
SpringBoot的@EnableAsync和@Async注解分析
這篇文章主要介紹了SpringBoot的@EnableAsync和@Async注解分析,Spring Boot是一個(gè)快速開發(fā)框架,可以幫助開發(fā)人員快速構(gòu)建基于Spring的應(yīng)用程序,需要的朋友可以參考下2023-07-07
Java從源碼看異步任務(wù)計(jì)算FutureTask
這篇文章主要介紹了Java從源碼看異步任務(wù)計(jì)算FutureTask,F(xiàn)utureTask就能夠很好的幫助我們實(shí)現(xiàn)異步計(jì)算,并且可以實(shí)現(xiàn)同步獲取異步任務(wù)的計(jì)算結(jié)果,具體是怎樣實(shí)現(xiàn)的,下面我們就一起來學(xué)習(xí)下面文章的具體內(nèi)容吧2022-04-04
Java中String類getBytes()方法詳解與完整實(shí)例
這篇文章主要給大家介紹了關(guān)于Java中String類getBytes()方法詳解與完整實(shí)例的相關(guān)資料,getBytes()是Java編程語言中將一個(gè)字符串轉(zhuǎn)化為一個(gè)字節(jié)數(shù)組byte[]的方法,需要的朋友可以參考下2023-10-10
Mybatis Plus select 實(shí)現(xiàn)只查詢部分字段
這篇文章主要介紹了Mybatis Plus select 實(shí)現(xiàn)只查詢部分字段的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Spring實(shí)現(xiàn)HikariCP連接池的示例代碼
在SpringBoot 2.0中,我們使用默認(rèn)連接池是HikariCP,本文講一下HikariCP的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2021-08-08
ObjectInputStream 和 ObjectOutputStream 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
ObjectInputStream 和 ObjectOutputStream 的作用是,對(duì)基本數(shù)據(jù)和對(duì)象進(jìn)行序列化操作支持。本文給大家詳細(xì)介紹了ObjectInputStream 和 ObjectOutputStream的相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧2017-05-05

