天天看點

集合架構(HashSet,HashMap,HashTable)

一,Map集合的基本操作

package fighting;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class MapDemo {

	/**
	 * Map:存儲一組成對的鍵值對象,key不要求有序,但不能重複;value也不要求有序,但允許重複。
	 * 
	 * Collection是單列集合,Map是雙列集合。
	 * 
	 * 1,添加
	 *    put(k,v)
	 *    pubAll()
	 * 2,删除
	 *    clear()
	 *    remove(k)
	 * 3,判斷
	 *    containsKey()
	 *    containsValue()
	 *    isEmpty()
	 * 4,擷取
	 *    get()
	 *    size()
	 *    values()
	 *    
	 *    entrySet()
	 *    keySet()
	 *    
	 * Map
	 *  |-HashTable:底層是哈希表資料結構,不可以存入null鍵和null值,線程同步,效率低。
	 *              用作鍵的對象必須實作hashCode方法和equals方法。
	 *  |-HashMap:底層是哈希表資料結構,允許使用null鍵和null值,該集合是不同步,效率高。
	 *  |-TreeMap:底層是二叉樹資料結構,線程不同步,可以用于給map集合中的鍵進行排序。
	 *  
	 *  TreeMap和Set很想,其實,Set底層就是使用了Map集合。
	 */
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		
		//添加元素
		map.put("01", "zhangsan001");
		map.put("02", "zhangsan002");
		map.put("03", "zhangsan003");
		
		System.out.println("containsKey:"+map.containsKey("02"));//containsKey:true
		
		//remove方法傳回值:與 key 關聯的舊值;如果 key 沒有任何映射關系,則傳回 null。(傳回 null 還可能表示該映射之前将 null 與 key 關聯。)
		System.out.println("remove:"+map.remove("022"));//remove:null
		System.out.println("remove:"+map.remove("02"));//remove:zhangsan002
		
		//可以通過get方法的傳回值來判斷一個鍵是否存在。
		System.out.println("get:"+map.get("02"));//get:null
		System.out.println("get:"+map.get("03"));//get:zhangsan003
		
		//下面這兩種特殊情況
		map.put(null, "aaa");
		System.out.println("get:"+map.get(null));//get:aaa
		map.put("04", null);
		System.out.println("get:"+map.get("04"));//get:null
		                                         //這行代碼說明,使用get方法擷取的null為空,不能說明沒有這個鍵,也可能是映射之前将null和key關聯
		
		//擷取map集合中所有的值
		Collection<String> coll = map.values();//這裡不要Collection<V> coll,實際使用中,要把V變成具體的類型。
		System.out.println(coll);//[zhangsan001, zhangsan003, null, aaa]
		
		//注意:添加元素時,如果出現相同的key,後添加的值會覆寫原有的鍵對應的值,并且傳回原來的這個值。
		System.out.println(map.put("ch", "中國"));//null
		System.out.println(map.put("ch", "中華人民共和國"));//中國
		System.out.println(map);//{ch=中華人民共和國, 01=zhangsan001, 03=zhangsan003, 04=null, null=aaa}

	}

}
           

二,Map集合的兩種取出方式:

package fighting;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapKeySet {

	/**
	 * map集合的兩種取出方式:
	 * 1,keySet:将map集合中所有的鍵存入到Set集合,因為Set具備疊代器,
	 *           是以可以使用疊代方式取出所有的鍵,再根據get方法,擷取每一個鍵對應的值
	 *           map集合沒有疊代器,map集合的取出原理:将map集合轉成Set,利用Set的疊代器疊代取出。
	 * 2,entrySet:傳回映射中包含的映射關系的Set視圖--Map.Entry<K,V>
	 * Map.Entry  其實Entry也是一個接口,他是Map接口中的一個内部接口。
	 * interface Map 
	 * {
	 * 	public static interface Entry{
	 *  	public abstract Object getKey();
	 *  	public abstract Object getValue();
	 *  }
	 * }
	 * class HashMap implements implements Map{
	 * 
	 * 	class xxx implements Map.Entry{
	 *  	public Object getKey(){};
	 *  	public Object getValue(){};
	 *  }
	 * }
	 */
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		//添加元素
		map.put("01", "zhangsan001");
		map.put("02", "zhangsan002");
		map.put("04", "zhangsan004");
		map.put("03", "zhangsan003");
		
		//擷取map集合中所有鍵的Set集合
		Set<String> keySet = map.keySet();
		//擷取疊代器
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()){
			String key = it.next();
			System.out.println("key:"+key+" value:"+map.get(key));
		}
		/*輸出結果
		 * key:01 value:zhangsan001
		 * key:03 value:zhangsan003
		 * key:04 value:zhangsan004
		 * key:02 value:zhangsan002
		 */
		
		Set<Map.Entry<String, String>> entryset = map.entrySet();
		Iterator<Map.Entry<String, String>> it1 = entryset.iterator();
		while(it1.hasNext()){
			Map.Entry<String, String> me = it1.next();
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key+":"+value);
		}
		/*輸出結果
		 * 01:zhangsan001
		 * 03:zhangsan003
		 * 04:zhangsan004
		 * 02:zhangsan002
		 */

	}

}
           

三,有關Map的一個小練習:

package fighting;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.itheima.Student;

public class MapDemo2 {

	/**
	 * 練習:每一個學生都有對應的歸屬地。
	 * 學生Student,位址String
	 * 學生屬性:姓名,年齡
	 * 注意:姓名和年齡相同的視為同一個學生
	 * 保證學生的唯一性。
	 * 
	 * 1,描述學生。
	 * 2,定義map容易,将學生作為鍵,位址作為值,存入。
	 * 3,擷取map集合中的元素。
	 * 
	 */
	public static void main(String[] args) {
		HashMap<Student0627,String> hm = new HashMap<Student0627,String>();
		
		hm.put(new Student0627("zhangsan001",22), "北京");
		hm.put(new Student0627("zhangsan002",23), "河北");
		hm.put(new Student0627("zhangsan003",24), "内蒙古");
		hm.put(new Student0627("zhangsan004",25), "天津");
		
		//第一種取出方式:keySet
		Set<Student0627> keySet =hm.keySet();
		Iterator<Student0627> it = keySet.iterator();
		while(it.hasNext()){
			Student0627 stu = it.next();
			System.out.println(stu+hm.get(stu));
		}
		/*
		 * zhangsan001...22北京
		 * zhangsan004...25天津
		 * zhangsan003...24内蒙古
		 * zhangsan002...23河北
		 */
		//第二種取出方式:entrySet
		Set<Map.Entry<Student0627, String>> entrySet = hm.entrySet();
		Iterator<Map.Entry<Student0627, String>> it1 = entrySet.iterator();
		while(it1.hasNext()){
			Map.Entry<Student0627, String> me= it1.next();
			System.out.println(me.getKey()+"..."+me.getValue());
		}
		/*
		 * zhangsan001...22...北京
		 *zhangsan004...25...天津
		 *zhangsan003...24...内蒙古
		 *zhangsan002...23...河北
		 */
		//再添加一條記錄,key已經存在,值不同
		hm.put(new Student0627("zhangsan001",22), "廣東");
		Set<Map.Entry<Student0627, String>> entrySet2 = hm.entrySet();
		Iterator<Map.Entry<Student0627, String>> it2 = entrySet.iterator();
		while(it2.hasNext()){
			Map.Entry<Student0627, String> me= it2.next();
			System.out.println(me.getKey()+"..."+me.getValue());
		}	
		/*
		 * zhangsan001...22...廣東   ----注意zhangsan001這一條歸屬地變成了"廣東"
		 * zhangsan004...25...天津
		 * zhangsan003...24...内蒙古
		 * zhangsan002...23...河北
		 */
	}

}
//注意:類的對象不确定要存到什麼集合中去,是以要保證儲存到任何集合中都不會出錯
//①要覆寫hashCode方法和equals方法,
//②還要實作Comparable接口,實作compareTo方法。
class Student0627 implements Comparable<Student0627>{
	private String name;
	private int age;
	public Student0627(String name,int age){
		this.name=name;
		this.age=age;
	}
	public int compareTo(Student0627 o) {
		int num = new Integer(this.age).compareTo(new Integer(o.age));
		if(num==0)
			return this.name.compareTo(o.name);
		return num;
	}
	public int hashCode(){
		return name.hashCode()+age*34;
	}
	public boolean equals(Object obj){
		if(!(obj instanceof Student0627)){
			throw new ClassCastException("類型不比對"); 
		}
		Student0627 s =(Student0627)obj;
		
		return this.name.equals(s.name)&&this.age==s.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 String toString(){
		return this.name+"..."+this.age;
		
	}
}
           

四,上一個小練習(MapDemo2)的需求更新:

package fighting;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo {

	/**
	 * MapDemo2的續:
	 * 需求:對學生對象的年齡進行升序排序。
	 * 需求2:按照學生對象的姓名升序排序
	 * 因為資料是以鍵值對形式存在的,是以要使用可以排序的Map集合--TreeMap
	 * 
	 */
	public static void main(String[] args) {
		//需求1
		TreeMap<Student0627,String> tm = new TreeMap<Student0627,String>();
		
		tm.put(new Student0627("bzhangsan003",23), "北京");
		tm.put(new Student0627("zhangsan001",21), "河北");
		tm.put(new Student0627("azhangsan004",24), "内蒙古");
		tm.put(new Student0627("zhangsan002",22), "天津");
		
		Set<Map.Entry<Student0627,String>> entrySet =tm.entrySet();
		Iterator<Map.Entry<Student0627,String>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Student0627,String> me =it.next();
			Student0627 stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+"..."+addr);
		}
		/*
		 * zhangsan001...21...河北
		 * zhangsan002...22...天津
		 * bzhangsan003...23...北京
		 * azhangsan004...24...内蒙古
		 */
		//需求2:如果想按照姓名升序進行排序,可以自定義比較器,傳入TreeMap構造方法
		TreeMap<Student0627,String> tm2 = new TreeMap<Student0627,String>(new StuNameComparator());
		
		tm2.put(new Student0627("bzhangsan003",23), "北京");
		tm2.put(new Student0627("zhangsan001",21), "河北");
		tm2.put(new Student0627("azhangsan004",24), "内蒙古");
		tm2.put(new Student0627("zhangsan002",22), "天津");
		
		Set<Map.Entry<Student0627,String>> entrySet2 =tm2.entrySet();
		Iterator<Map.Entry<Student0627,String>> it2 = entrySet2.iterator();
		while(it2.hasNext()){
			Map.Entry<Student0627,String> me =it2.next();
			Student0627 stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+"..."+addr);
		}
		/*
		 * azhangsan004...24...内蒙古
		 * bzhangsan003...23...北京
		 * zhangsan001...21...河北
		 * zhangsan002...22...天津
		 */
	}

}
class StuNameComparator implements Comparator<Student0627>{

	public int compare(Student0627 s1, Student0627 s2) {
		int num  =s1.getName().compareTo(s2.getName());
		if(num==0){
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num;
	}
	
}
           

五,有關Map的第二個小練習--字母出現的次數:

package fighting;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo1 {

	/**
	 * 練習:
	 * "adsgljrgsgjfdgf"擷取該字元串中的字母出現的次數。
	 * 希望列印結果:a(1)c(2)...
	 * 
	 * 通過結果發現,每一個字母都有對應的次數,
	 * 說明字母和次數之間都有映射關系。
	 * 
	 * 注意了,當發現有映射關系時,就可以選擇Map集合,
	 * 因為Map集合中存放就是映射關系。
	 * 
	 * 思路:
	 * 1,将字元串轉換成字元數組,因為要對每一個字元進行操作。
	 * 2,定義一個map集合,因為列印結果的字母有順序,是以使用TreeMap集合,
	 * 3,周遊字元數組,将每一個字母作為鍵,去查map集合,
	 *    如果傳回null,就将該字母和1存入map集合;
	 *    如果傳回不是null,說明該字母在map集合内已經存在,并有對應的次數,
	 *    那麼就擷取該次數并自增,讓後讓該字母和自增後的次數覆寫到集合中,覆寫到原來的鍵和對應的值
	 * 4,将Map集合的資料指定的字元串形式傳回
	 */
	public static void main(String[] args) {
		String str = carCount("adsgljrgsgjfdgf");
		System.out.println(str);

	}

	public static String carCount(String str){
		char[] chs = str.toCharArray();
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		int count=0;
		for(int x=0;x<chs.length;x++){
			if(chs[x]>='a'&&chs[x]<='z'||chs[x]>='A'&&chs[x]<='Z'){//非字母不用計算個數
				continue;
			}
			Integer value = tm.get(chs[x]);
			//方法二
			if(value!=null){//不等于空,說明已經存在這個key,那麼把key對應的值賦給count,再加一
				count = value;
			}
			count++;
			tm.put(chs[x], count);
			count =0;
			//方法一
			/*if(value==null){
				value = 1;
				tm.put(chs[x], 1);
			}else{
				value++;
				tm.put(chs[x], value);
			}*/
		}
		StringBuilder sb = new StringBuilder();
		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Character,Integer> me= it.next();
			Character ch = me.getKey();
			Integer value = me.getValue();
			sb.append(ch+"("+value+")");
		}
		return sb.toString();//把sb轉換成字元串類型傳回,這裡toString不能省略
	}
}
           

六,Map擴充知識:大集合嵌套小集合、一對多映射

package fighting;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;


public class MapDemo1 {

	/**
	 * Map擴充知識:
	 * map集合被使用是因為具備映射關系。。
	 * 
	 * 需求:一個學校有多個班級,每個班級有多名學生,利用Map周遊所有學生
	 * 比如:學校有預熱班和就業班
	 * "預熱班","1号","張三"
	 * "預熱班","2号","李四"
	 * "就業班","1号","張三"
	 * "就業班","2号","李四"
	 * 
	 * 需求2:把學号和學生姓名封裝成學生對象進行操作。
	 * 
	 * 大集合裡嵌套小集合
	 * 一對多映射
	 */
	public static void main(String[] args) {
		//分别定義學校、預熱班、就業班
		HashMap<String,HashMap<String,String>> school = new HashMap<String,HashMap<String,String>>();
		HashMap<String,String> yure=new HashMap<String,String>();
		HashMap<String,String> jiuye =new HashMap<String,String>();
		//把班級資訊添加到學校集合
		school.put("預熱班", yure);
		school.put("就業班", jiuye);
		//把學生資訊添加到班級集合
		yure.put("1号", "張三");
		yure.put("2号", "李四");
		//把學生資訊添加到班級集合
		jiuye.put("1号", "張三er");
		jiuye.put("2号", "李四er");
		//周遊輸出,
		Iterator<String> it = school.keySet().iterator();//擷取學校的所有班級資訊
		while(it.hasNext()){
			String roomName = it.next();//班級名稱--預熱班、就業班
			HashMap<String,String> room = school.get(roomName);//班級對應的集合--yure、jiuye
			Iterator<String> it1 = room.keySet().iterator();//班級裡學生資訊的學号集合
			while(it1.hasNext()){
				String id = it1.next();//學号
				System.out.println(roomName+id+"::"+room.get(id));
			}
			
		}
		System.out.println("---------------------------把學生封裝成對象(Student27)實作如下--------------------------------");
		demo();
		
	}
	public static void demo(){
		//把學生資訊儲存到List集合裡,就是說每一個班級對應一個學生的List集合,
		//擷取班級資訊後,就可以擷取學生的一個List集合,再疊代這個List集合就可以得到所有學生資訊。
		HashMap<String,List<Student27>> hm = new HashMap<String,List<Student27>>();
		
		List<Student27> yure = new ArrayList<Student27>();
		List<Student27> jiuye = new ArrayList<Student27>();

		hm.put("預熱班", yure);
		hm.put("就業班", jiuye);
		
		yure.add(new Student27("1号", "張三"));
		yure.add(new Student27("2号", "李四"));
		jiuye.add(new Student27("1号", "張三er"));
		jiuye.add(new Student27("2号", "李四er"));
		
		
		Iterator<String> it = hm.keySet().iterator();
		while(it.hasNext()){
			String roomName = it.next();
			List<Student27> room = hm.get(roomName);
			Iterator<Student27> it1 = room.iterator();
			while(it1.hasNext()){
				Student27 stu = it1.next();
				System.out.println(roomName+stu.getId()+"::"+stu.getName());
			}
			
		}
		
	}

}
//把學号和學生姓名封裝成學生對象--學生類
class Student27 {
	private String id;
	private String name;
	public Student27(String id,String name){
		this.id=id;
		this.name=name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
}