HashMap常見鍵、LinkedHashMap以及TreeMap的理解

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集合

先簡單的說說TreeSetTreeMap的區別?

TreeMapMap接口常用的子實現類,而TreeSetSet接口常用的子實現類,TreeSet底層是通過TreeMap來實現的,(就相當於HashSet底層是通過HashMap來實現的),TreeMap是依靠紅黑樹結構來實現的

相同點:他們都是有序的集合

不同點:他們實現於不同的接口

存儲的類型數量不同(treeSet只能存儲一種類型,TreeMap可以存儲存儲兩種類型(keyvalue))

那讓我們看看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
 

讓我們再看看HashtableHashMap的區別?

面試題:

  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(字符串緩衝區)、vectorlist集合子實現類)、HashtableMap集合子實現類)

讓我們用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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章