聯(lián)系
Java中的Map類似于OC的Dictionary,都是一個(gè)個(gè)鍵值對(duì)組成,一鍵對(duì)應(yīng)一值。我在之前的文章中講解過(guò)Set,其實(shí)在JAVA底層Set依賴的也是Map,那我們都知道,Set是單列的(只有值),而Map是雙列的,怎么會(huì)是Set依賴Map呢?其實(shí)做法也很簡(jiǎn)單,Set將Key隱藏,只允許訪問(wèn)value就實(shí)現(xiàn)了Set的單列效果。
功能
*a:添加功能
* V put(K key,V value):添加元素。
* 如果鍵是第一次存儲(chǔ),就直接存儲(chǔ)元素,返回null
* 如果鍵不是第一次存在,就用值把以前的值替換掉,返回以前的值
Map<String, Interger> map = new HashMap();
map.put("張三",23);
這里需要注意Map中的重復(fù)的鍵不存儲(chǔ),值覆蓋返回
* b:刪除功能
* void clear():移除所有的鍵值對(duì)元素
* V remove(Object key):根據(jù)鍵刪除鍵值對(duì)元素,并把值返回
Map<String, Interger> map = new HashMap();
map.put("張三",23);
map.remove("張三");根據(jù)鍵刪除元素
* c:判斷功能
* boolean containsKey(Object key):判斷集合是否包含指定的鍵
* boolean containsValue(Object value):判斷集合是否包含指定的值
* boolean isEmpty():判斷集合是否為空
Map<String, Interger> map = new HashMap();
map.put("張三",23);
System.out.println(map.containsKey("張三")); //判斷集合是否包含指定的鍵
System.out.println(map.containsValue(100)); //判斷集合是否包含指定的值
* d:獲取功能
* Set<Map.Entry<K,V>> entrySet():
* V get(Object key):根據(jù)鍵獲取值
* Set<K> keySet():獲取集合中所有鍵的集合
* Collection<V> values():獲取集合中所有值的集合
Map<String, Interger> map = new HashMap();
map.put("張三",23);
Collection<Integer> c = map.values();
* e:長(zhǎng)度功能
* int size():返回集合中的鍵值對(duì)的個(gè)數(shù)
Map<String, Interger> map = new HashMap();
map.put("張三",23);
System.out.println(map.size());
size()方法以鍵值對(duì)的個(gè)數(shù)統(tǒng)計(jì),上述map.size()為1而不是2。
Map的遍歷
方式一
//通過(guò)獲取所有的鍵來(lái)遍歷值
Map<String, Integer> map = new HashMap<>();
map.put("張三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("趙六", 26);
Set<String> keySet = map.keySet(); //獲取所有鍵的集合
Iterator<String> it = keySet.iterator(); //獲取迭代器
while(it.hasNext()) { //判斷集合中是否有元素
String key = it.next(); //獲取每一個(gè)鍵
Integer value = map.get(key); //根據(jù)鍵獲取值
System.out.println(key + "=" + value);
}
使用迭代器遍歷,但是有些復(fù)雜,可以改進(jìn)
方式二 (方式一改進(jìn),較簡(jiǎn)單)
這種遍歷方式類似于OC中for···in語(yǔ)法
//使用增強(qiáng)for循環(huán)遍歷
for(String key : map.keySet()) { //map.keySet()是所有鍵的集合
System.out.println(key + "=" + map.get(key));
}
方式三 鍵值對(duì)對(duì)象遍歷
//Map.Entry說(shuō)明Entry是Map的內(nèi)部接口,將鍵和值封裝成了Entry對(duì)象,并存儲(chǔ)在Set集合中
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
//獲取每一個(gè)對(duì)象
Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
while(it.hasNext()) {
//獲取每一個(gè)Entry對(duì)象
Map.Entry<String, Integer> en = it.next(); //父類引用指向子類對(duì)象
//Entry<String, Integer> en = it.next(); //直接獲取的是子類對(duì)象
String key = en.getKey(); //根據(jù)鍵值對(duì)對(duì)象獲取鍵
Integer value = en.getValue(); //根據(jù)鍵值對(duì)對(duì)象獲取值
System.out.println(key + "=" + value);
}
方式四 (方式三改進(jìn))
for(Entry<String, Integer> en : map.entrySet()) {
System.out.println(en.getKey() + "=" + en.getValue());
}
LinkedHashMap
LinkedHashMap可以保證怎么存就怎么取
public static void main(String[] args) {
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
lhm.put("張三", 23);
lhm.put("李四", 24);
lhm.put("趙六", 26);
lhm.put("王五", 25);
System.out.println(lhm);
}
TreeMap
利用TreeMap可實(shí)現(xiàn)對(duì)鍵的自定義排序,同時(shí)鍵應(yīng)為自定義類對(duì)象,同時(shí)需要在自定義類中重寫compareTo方法,和hashSet里面的排序大致相同。
//按照Student的姓名排序,姓名相同按照年齡排序
public static void main(String[] args) {
//demo1();
TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getName().compareTo(s2.getName()); //按照姓名比較
return num == 0 ? s1.getAge() - s2.getAge() : num;
}
});
tm.put(new Student("張三", 23), "北京");
tm.put(new Student("李四", 13), "上海");
tm.put(new Student("趙六", 43), "深圳");
tm.put(new Student("王五", 33), "廣州");
System.out.println(tm);
}
利用HashMap統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)的次數(shù)
核心思想就是利用HashMap的containsKey()來(lái)判斷是否重復(fù)。
/**
* * A:案例演示
* 需求:統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)的次數(shù)
*
* 分析:
* 1,定義一個(gè)需要被統(tǒng)計(jì)字符的字符串
* 2,將字符串轉(zhuǎn)換為字符數(shù)組
* 3,定義雙列集合,存儲(chǔ)字符串中字符以及字符出現(xiàn)的次數(shù)
* 4,遍歷字符數(shù)組獲取每一個(gè)字符,并將字符存儲(chǔ)在雙列集合中
* 5,存儲(chǔ)過(guò)程中要做判斷,如果集合中不包含這個(gè)鍵,就將該字符當(dāng)作鍵,值為1存儲(chǔ),如果集合中包含這個(gè)鍵,就將值加1存儲(chǔ)
* 6,打印雙列集合獲取字符出現(xiàn)的次數(shù)
*/
public static void main(String[] args) {
//1,定義一個(gè)需要被統(tǒng)計(jì)字符的字符串
String s = "aaaabbbbbccccccccccccc";
//2,將字符串轉(zhuǎn)換為字符數(shù)組
char[] arr = s.toCharArray();
//3,定義雙列集合,存儲(chǔ)字符串中字符以及字符出現(xiàn)的次數(shù)
HashMap<Character, Integer> hm = new HashMap<>();
//4,遍歷字符數(shù)組獲取每一個(gè)字符,并將字符存儲(chǔ)在雙列集合中
for(char c: arr) {
//5,存儲(chǔ)過(guò)程中要做判斷,如果集合中不包含這個(gè)鍵,就將該字符當(dāng)作鍵,值為1存儲(chǔ),如果集合中包含這個(gè)鍵,就將值加1存儲(chǔ)
/*if(!hm.containsKey(c)) { //如果不包含這個(gè)鍵
hm.put(c, 1);
}else {
hm.put(c, hm.get(c) + 1);
}*/
hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
}
//6,打印雙列集合獲取字符出現(xiàn)的次數(shù)
for (Character key : hm.keySet()) { //hm.keySet()代表所有鍵的集合
System.out.println(key + "=" + hm.get(key));//hm.get(key)根據(jù)鍵獲取值
}
}
案例演示:
集合嵌套之HashMap嵌套HashMap
需求:
一個(gè)年級(jí)有很多班,
一班定義為一個(gè)雙列結(jié)合,鍵是學(xué)生對(duì)象,值是學(xué)生的歸屬地,
二班定義為一個(gè)雙列結(jié)合,鍵是學(xué)生對(duì)象,值是學(xué)生的歸屬地。
無(wú)論一班二班都是班級(jí)對(duì)象,所以為了編譯統(tǒng)一管理,把這些班級(jí)對(duì)象添加到某個(gè)年級(jí)中。
//定義一班
HashMap<Student, String> hm88 = new HashMap<>();
hm88.put(new Student("張三", 23), "北京");
hm88.put(new Student("李四", 24), "北京");
hm88.put(new Student("王五", 25), "上海");
hm88.put(new Student("趙六", 26), "廣州");
//定義二班
HashMap<Student, String> hm99 = new HashMap<>();
hm99.put(new Student("唐僧", 1023), "北京");
hm99.put(new Student("孫悟空",1024), "北京");
hm99.put(new Student("豬八戒",1025), "上海");
hm99.put(new Student("沙和尚",1026), "廣州");
//定義年級(jí)
HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
hm.put(hm88, "一班");
hm.put(hm99, "二班");
//遍歷雙列集合
for(HashMap<Student, String> h : hm.keySet()) { //hm.keySet()代表的是雙列集合中鍵的集合
String value = hm.get(h); //get(h)根據(jù)鍵對(duì)象獲取值對(duì)象
//遍歷鍵的雙列集合對(duì)象
for(Student key : h.keySet()) { //h.keySet()獲取集合總所有的學(xué)生鍵對(duì)象
String value2 = h.get(key);
System.out.println(key + "=" + value2 + "=" + value);
}
}
hashMap和hashTable的區(qū)別
共同點(diǎn):
底層都是哈希算法,都是雙列集合
區(qū)別:
- HashMap是線程不安全的,效率高,JDK1.2版本,Hashtable是線程安全的,效率低,JDK1.0版本的
- HashMap可以存儲(chǔ)null鍵和null值,Hashtable不可以存儲(chǔ)null鍵和null值