HashMap四種常見的鍵的類型:
HashMap<String,String>、HashMap<Integer,String>、HashMap<String,Student>、HashMap<Student,String>(其中的Student只是我們自定義的一個學生類)
例如:
package com.westos.HashMap;
import java.util.HashMap;
import java.util.Set;
/**
*HashMap(String (學號),String(姓名))形式
*/
public class HashMapDome {
public static void main(String[] args) {
//創建HashMap集合的對象
HashMap<String,String> map=new HashMap<String,String>();
map.put("132614", "曹乾");
map.put("132118", "劉崇華");
map.put("132194", "馬玉超");
map.put("132668", "宋曉波");
map.put("132668", "於金樂");
map.put("132614", "井傑");
//收集集合中所有的鍵對象
Set<String> key = map.keySet();
//增強for循環
for(String str:key) {
//獲取所有與鍵對應的值
String value = map.get(str);
System.out.println(str+"----"+value);
}
}
}
運行結果:
132614----井傑
132118----劉崇華
132668----於金樂
132194----馬玉超
例如:
package com.westos.HashMap;
import java.util.HashMap;
import java.util.Set;
/**
*HashMap<Integer(年齡),String(姓名)>形式
*
*/
public class HashMapDome2 {
public static void main(String[] args) {
//創建HashMap集合的對象
HashMap<Integer,String> map=new HashMap<Integer,String>();
//添加集合中的元素
map.put(25, "Angelababy");
map.put(23, "吳宣儀");
map.put(24, "趙星星");
map.put(22, "孟美岐");
map.put(25, "迪麗熱巴");
//獲取集合中所有的鍵
Set<Integer> keySet = map.keySet();
//增強for循環
for(Integer key:keySet) {
String value = map.get(key);
//遍歷出每一個鍵和它對應的值
System.out.println(key+"----"+value);
}
}
}
運行結果:
22----孟美岐
23----吳宣儀
24----趙星星
25----迪麗熱巴
package com.westos.HashMap;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
package com.westos.HashMap;
/**
* HhashMap<String(學號),Student(學生的姓名和年齡)
*/
import java.util.HashMap;
import java.util.Set;
public class HashMapDome3 {
public static void main(String[] args) {
//創建HashMap集合對象
HashMap<String,Student> map=new HashMap<String,Student>();
//創建學生對象
Student s1=new Student("迪麗熱巴",25);
Student s2=new Student("吳宣儀",23);
Student s3=new Student("孟美岐",23);
Student s4=new Student("趙星星",24);
Student s5=new Student("迪麗熱巴",25);
//將學生對象添加進集合中去
map.put("001", s1);
map.put("002", s2);
map.put("003", s3);
map.put("004", s4);
map.put("005", s5);
//獲取集合中所有的鍵
Set<String> set = map.keySet();
//增強for循環
for(String key:set) {
Student value = map.get(key);
System.out.println(key+":"+value.getName()+"----"+value.getAge());
}
}
}
運行結果:
001:迪麗熱巴----25
002:吳宣儀----23
003:孟美岐----23
004:趙星星----24
005:迪麗熱巴----25
例如:
學生類就用了上面的那個學生類
package com.westos.HashMap;
/**
* HashMap<Student,String>類型
*/
import java.util.HashMap;
import java.util.Set;
public class HashMapDome4 {
public static void main(String[] args) {
//創建HashMap集合對象
HashMap<Student,String> map=new HashMap<Student,String>();
//創建學生對象
Student s1=new Student("迪麗熱巴",25);
Student s2=new Student("吳宣儀",23);
Student s3=new Student("孟美岐",23);
Student s4=new Student("趙星星",24);
Student s5=new Student("迪麗熱巴",25);
//將學生對象添加進集合中去
map.put( s1,"001");
map.put( s2,"002");
map.put( s3,"003");
map.put( s4,"004");
map.put( s5,"005");
//獲取集合中所有的鍵
Set<Student> set = map.keySet();
//for循環
for(Student key:set) {
String value = map.get(key);
System.out.println(key.getName()+"="+key.getAge()+"--"+value);
}
}
}
運行結果:
趙星星=24--004
吳宣儀=23--002
迪麗熱巴=25--005
孟美岐=23--003
從最後的這個HashMap<Student,String>類型中當我們的鍵(就是學生類的對象)內容一樣時,運行結果中後面的那個一樣的鍵的值替代了前面的那個鍵的值,要想達到這種去重的效果,必須在自定義類中添加重寫方法(equals方法和HashCode方法),因爲我們是自定義類,調用自定義對象時,在底層代碼中系統並沒有幫我們重寫這兩個方法,所以必須我們自己手動重寫,否則達不到去重的效果
LinkedHashMap集合
我們都知道HashMap的無序性(存儲和輸出的順序不一致),但是當我們需要HashMap的唯一性,還想要它能有序的輸出,應該怎麼做呢?
LinkHashMap可以幫我們解決這個問題:
它是基於哈希表和鏈接列表實現的
其中HashMap可以解決唯一性的問題,Linked可以解決有序性的問題
例如:
package com.westos.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
public class LinkedHashMapDome {
public static void main(String[] args) {
//創建集合對象
LinkedHashMap<String,String> link=new LinkedHashMap<String,String>();
//向集合中添加元素
link.put("迪麗熱巴", "美女");
link.put("吳宣儀", "少女");
link.put("孟美岐", "大哥");
link.put("古天樂", "型男");
link.put("蕭炎", "鬥帝");
//獲取集合中所有的鍵
Set<String> set = link.keySet();
//for循環
for(String key:set) {
//獲取鍵對應的值
String value = link.get(key);
System.out.println(key+"----"+value);
}
}
}
運行結果:
迪麗熱巴----美女
吳宣儀----少女
孟美岐----大哥
古天樂----型男
蕭炎----鬥帝
TreeMap集合
前面我們學習了treeSet集合,其中瞭解兩種遍歷方式:自然排序和比較器排序,接下來讓我們看看TreeMap集合
先簡單的說說TreeSet與TreeMap的區別?
TreeMap是Map接口常用的子實現類,而TreeSet是Set接口常用的子實現類,TreeSet底層是通過TreeMap來實現的,(就相當於HashSet底層是通過HashMap來實現的),TreeMap是依靠紅黑樹結構來實現的
相同點:他們都是有序的集合
不同點:他們實現於不同的接口
存儲的類型數量不同(treeSet只能存儲一種類型,TreeMap可以存儲存儲兩種類型(key和value))
那讓我們看看TreeMap存儲自定義對象的例子
例如:
先創建一個自定義類
package com.westos.TreeMap;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
再創建一個測試類:
package com.westos.TreeMap;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDome {
public static void main(String[] args) {
//創建TreeMap集合對象,並且運用比較器排序的方式
TreeMap<Student,String> map=new TreeMap<Student,String>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// return 0;
//按年齡(從小到大)來排序
int num=s1.getAge()-s2.getAge();
//當年齡大小一樣時,比較姓名
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//創建學生類對象
Student s1=new Student("旺達",29);
Student s2=new Student("幻視",32);
Student s3=new Student("黑寡婦",32);
Student s4=new Student("雷神",35);
Student s5=new Student("託尼",37);
Student s6=new Student("託尼",37);
//將學生對象添加到集合中
map.put(s1, "菜鳥");
map.put(s2, "美女");
map.put(s3, "御姐");
map.put(s4, "錘子");
map.put(s5, "鋼鐵俠");
map.put(s6, "小辣椒");
//獲取集合中所有的鍵
Set<Student> set = map.keySet();
for(Student key:set) {
//獲取鍵所對應的所有的值
String value = map.get(key);
System.out.println(key.getName()+","+key.getAge()+":"+value);
}
}
}
運行結果:
旺達,29:菜鳥
幻視,32:美女
黑寡婦,32:御姐
雷神,35:錘子
託尼,37:小辣椒
前面我們學習了ArrayList集合的嵌套遍歷,接下來讓我們看看HashMap集合的嵌套
例如:
package com.westos.HashMap2;
import java.util.HashMap;
import java.util.Set;
/**
* 一個大集合LPL(中國LOL戰隊)HashMap<HashMap<Person>>
* 三個小集合HashMap<Person> RNG戰隊,EDG戰隊,IG戰隊
*
*/
public class HashMapTest {
public static void main(String[] args) {
//創建大集合
HashMap<String,HashMap<String,String>> lol=new HashMap<String,HashMap<String,String>>();
//創建第一個小集合
HashMap<String,String> rng=new HashMap<String,String>();
//向集合中添加元素
rng.put("Uzi", "ADC");
rng.put("Mlxg", "打野");
//將小集合添加到大集合中
lol.put("RNG", rng);
//創建第二個小集合
HashMap<String,String> edg=new HashMap<String,String>();
//向集合中添加元素
edg.put("那美", "ADC");
edg.put("廠長", "打野");
//添加到大集合中
lol.put("EDG",edg);
//創建第三個小集合
HashMap<String,String> ig=new HashMap<String,String>();
//添加元素
ig.put("Acorn","ADC");
ig.put("Clearlove","打野");
//添加到大集合中
lol.put("IG", ig);
//獲取大集合中的所有鍵
Set<String> set = lol.keySet();
//for循環遍歷
for(String hash:set) {
System.out.println(hash+":");
//獲取大集合中的所有值,返回的是小集合的類型
HashMap<String, String> value = lol.get(hash);
//然後再獲取小集合的所有鍵,就相當於我們創建一個HashMap集合給他遍歷,不要管上面的那些大集合
Set<String> Hashset = value.keySet();
//循環遍歷小集合
for(String key:Hashset) {
//獲取小集合中的所有值
String str = value.get(key);
System.out.println("\t"+key+":"+str);
}
}
}
}
運行結果:
EDG:
廠長:打野
那美:ADC
RNG:
Uzi:ADC
Mlxg:打野
IG:
Clearlove:打野
Acorn:ADC
讓我們再看看Hashtable與HashMap的區別?
面試題:
HashMap集合和Hashtable的區別?
共同點:都是map接口的實現類,都是基於哈希表的實現類
HashMap集合線程不安全的類,不同步,執行效率高(允許鍵和值是null的)
Hashtable集合線程安全的類,同步,執行效率低(不允許有null鍵和null值)
package com.westos.HashMap2;
import java.util.HashMap;
import java.util.Hashtable;
public class HashTable {
public static void main(String[] args) {
//創建HashMap集合對象
HashMap<String,String> hm=new HashMap<String,String>();
//創建Hashtable集合對象
Hashtable<String,String> ht=new Hashtable<String,String>();
hm.put(null, "java");
//ht.put(null, "baby");//Exception in thread "main" java.lang.NullPointerException
System.out.println("hm:"+hm);
System.out.println("ht:"+ht);
}
}
運行結果:
hm:{null=java}
ht:{}
由上例看出
Hashtable集合不論是鍵還是值都不允許有null值,否則編譯通過,運行就會報錯,而HashMap中的則允許有null值,編譯和運行都會通過
我們目前學習過的線程安全的類有:StringBuffer(字符串緩衝區)、vector(list集合子實現類)、Hashtable(Map集合子實現類)
讓我們用HashMap集合來看一個集合
需求:
字符串:比如: aaaaabbbbcccddddee ,最終控制檯要出現的結果:a(5)b(4)c(3)d(3)e(2)
package com.westos.TreeMap;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
/**
*需求:
* 字符串:比如: aaaaabbbbcccddddee ,最終控制檯要出現的結果:a(5)b(4)c(3)d(3)e(2)
*
*思路:
* 1)改進:鍵盤錄入一個字符串
* 2)創建一個HashMap集合key:Character,Value:Integer
* 3)將錄入的字符串轉換成字符數組
* 4)遍歷可以獲取每一個字符
*
* 5)將元素添加到對應的HashMap集合中
* 使用的put(key,value): 通過判斷值是否null ,如果是null表示第一次存儲
* 集合對象.put(ch,1) ;
* 否則,不是null
* Integer那個值++;
* 集合對象.put(ch,變量Integer值) ;
*
* 6)遍歷HashMap集合即可
*
*/
public class HashMapDome {
public static void main(String[] args) {
//鍵盤錄入
Scanner sc=new Scanner(System.in);
System.out.println("輸入一個字符串...");
String str=sc.nextLine();
//將字符春轉換成字符數組
char[] array = str.toCharArray();
//創建集合對象
HashMap<Character,Integer> map=new HashMap<Character,Integer>();
//遍歷字符數組
for(Character ch:array) {
//獲取數組中的每一個字符
Integer value = map.get(ch);
//判斷數組是否爲null,如果是給集合中添加元素
if(value==null) {
map.put(ch, 1);
}else {
value++;
map.put(ch,value);
}
}
//創建一個字符串緩衝區
StringBuffer sb=new StringBuffer();
//獲取集合的鍵
Set<Character> set = map.keySet();
//遍歷HashMap集合的值
for(Character key:set) {
//獲取集合中的值
Integer num = map.get(key);
sb.append(key).append("(").append(num).append(")");
}
//將緩衝區中的字符轉換成字符串
String str2 = sb.toString();
System.out.println(str2);
}
}
運行結果:
輸入一個字符串...
helloworld
r(1)d(1)e(1)w(1)h(1)l(3)o(2)