天天看點

【Map集合總結】HashMap---Hashtable---TreeMap三者的差別和相關的應用!!

一:Map集合:

其實就是存儲“鍵到值”的映射的集合,簡單的了解就是想存儲一對一對的夫妻似得!

了解:【鍵就是丈夫(key),值就是老婆(value),是一一對應的關系!】

【但是注意】:一個映射不能包含重複的鍵(不能把同一個丈夫存儲兩次),每一個鍵最多隻能映射到一個值(一個丈夫隻能對應一個老婆!)

Map當中存儲的全是這樣的“鍵值對”(一對一對的!)而且必須保證其唯一性!

Collection是單列模式集合,而Map是雙列模式集合,關于一些基本都是添加,修改,删除,檢視的方法就不再一一介紹了,在API幫助文檔中學習一下就行!

下面隻是說一個比較特殊的添加方法:請看執行個體分析:

/*
【重點】
1.put("","")方法:的傳回值是和該健值相同的之前一個健值的具體内容,類型為健值内容的類型
*/
import java.util.*;
class  HashMapDemo1
{
	public static void main(String[] args) 
	{
		Map<String,String> map=new HashMap<String,String>();
	
		/*
		map.put("01","afa");
		map.put("01","afa");
		map.put("01","afa");
		map.put("01","afa");
		map.put("01","afaf");

		sop(map); 
		//列印結果是{01=afa},隻有一個元素,說明被後面相同鍵所對應的值替換掉了
		sop("該方法的傳回值:"+map.put("01","wangke"));
		//該方法的傳回值:afaf,并不是wangkeze,說明此時傳回的值是前一個相同鍵位對應的值。*/
		
		/*
		map.put("01","afa");
		map.put("02","afa");
		map.put("03","afa");
		map.put("03","wang");
		map.put("04","afa");
		map.put("05","afa");
		sop(map);//{04=afa, 05=afa, 01=afa, 02=afa, 03=afa}//說明存入的鍵值是無序性的*/
		
		
		/*
		map.put("01","afa");
		map.put("02","afa");
		map.put("03","afa");
		map.put("04","afa");
		map.put("05","afa");
		map.put("03","wang");
		sop(map); //{04=afa, 05=afa, 01=afa, 02=afa, 03=wang}//03鍵值被改變了*/

		map.put("01","afa");
		map.put("02","afa");
		map.put("03","afa");
		map.put("04","afa");
		map.put("05","afa");
		sop(map.put("06","afa")); //傳回值是null
		Set<String> set=map.keySet();
		Iterator<String> i=set.iterator();
		while (i.hasNext())
		{
			String key=i.next();
			String value=map.get(key);
			sop("鍵值:"+key+"内容:"+value);
		}

		/*取出的結果為:
		鍵位:04内容:afa
		鍵位:05内容:afa
		鍵位:01内容:afa
		鍵位:02内容:afa
		鍵位:03内容:afa
		*/

	}
	public static void sop(Object obj) 
	{
		System.out.println(obj);
	}
}
           

二:該集合主要分為三個重點的實作類:

【Hashtable】:看意思嘛,就是hash表,對!它的底層資料結構就是hash表,它出現在JDK1,.0中,是同步的線程,非常安全!但是效率不是很高!

 【HashMap】:簡單說就是【Hashtable】的更新版本:在JDK1.2之後就是 【HashMap】了,但是線程不同步,執行效率高,多線程中,自己必須要加鎖才行!

【TreeMap】:底層資料結構是二叉樹的原理!大家應該都比較熟悉了,在set集合中,其實作類TreeSet就是二叉樹的資料結構,隻不過這個是單列集合!

三:【重點】keySet方法   和   entrySet方法的應用:

還是用執行個體來分析說明吧!

/*
【重點1】
1.keySet()方法:取出的是所有的健值,會放在set集合中
再用set集合中的疊代方式取出健值用map的get()方法去依次取出對應的内容

【重點2】entrySet()方法:
1.該方法主要是把map集合中的”映射對應項“取出存在了set集合中
其對應項的關系類型是Map.Entry
2.用set集合中疊代的方式取出對應項,再用其Map.Entry類中自有的方法getKey()
和getValue()分别取出健值和對應的内容的值
*/

import java.util.*;
class  EntrySetDemo2
{
	public static void main(String[] args) 
	{
		Map<String,String> map=new HashMap<String,String>();
		map.put("001","wangming");
		map.put("002","wang");
		map.put("003","wangming");
		map.put("004","wangfsd");
		map.put("005","wangmif");
		map.put("006","wfsfang");

		/*
		這裡用keySet方法進行
		*/
		//這裡是把HashMap集合的中key元素轉移到set集合中去
		Set<String> set=map.keySet(); 

		//通過疊代的方式,取出set集合中的元素(也就是原來HashMap中的鍵值)
		Iterator<String> it=set.iterator();
		while (it.hasNext())
		{
			String key=it.next(); //這就是疊代取出的鍵值

			//通過HashMap集合中的get方法又去把鍵值作為參數傳遞,得到HashMap中的value值
			String value=map.get(key); 
			
			sop(key+":"+value);
		}


		/*
		以下是用entry()的方法
		*/

		//這是用map的entrySet()方法取出對應項存在set集合中
		Set<Map.Entry<String,String>> mapEntry=map.entrySet();
		
		//用疊代的方式取出Map.Entry的類型;
		Iterator<Map.Entry<String,String>> i=mapEntry.iterator();
		
		//再用其Map.Entry類中的方法getKey()和getValue()去取得健值和内容
		while (i.hasNext())
		{	Map.Entry<String,String> entry=i.next();
			
			//取出健值和對應的内容值
			String key=entry.getKey();
			String value=entry.getValue();

			sop(key+":"+value);
		}

	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

/*【分析Map.Entry類型的來曆】
1.Entry是Map接口中的一個接口;
2.該接口是對外開放的,而且是靜态的,因為能直接被Map.的方式調用
3.該Entry接口中的方法有兩個getKey()和getValue(),肯定是抽象的,需要實作類去實作;
4.由實作類HashMap去實作了Map接口和另外一個類去實作内置的Entry接口,并且實作了抽象的兩個方法;
【總結】這裡就是用到了内部類的思想,為什麼要把Entry接口定義在Map接口内部,是因為必須先要有集合,
才能有對應項的存在
*/
/*interface Map
{
	public static interface Entry
	{
		public abstract Object getKey();
		public abstract Object getValue();
	}
}

class HashMap implements Map
{
	class Xxx implements Entry
	{
		public Object getKey(){}
		public Object getValue(){}
	}
}
*/
           

四、中級應用:關于對象加入Map集合的方法,一樣的請看執行個體分析就能掌握了

/*
題目:每一個學生都有對應的歸屬地;
學生;Student 位址: address:String
學生:屬性中姓名和年齡相同的視為同一個學生
必須保證學生的唯一性
編寫這樣一個程式去實作上述内容

【分析】
1.先定義一個學生類;
2.每個學生指的是:【姓名和年齡】整體屬性和其它的不能一樣,否則就是同一個學生
3.用Map對應的關系映射去做出”一個學生對應一個位址“
*/
import java.util.*;

//定義按照上面要求的一個學生類
class Student implements Comparable<Student>
{
	private String name;
	private int age;
	
	Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	
	//為了保證學生類中學生的唯一性,覆寫了hashCode()的方法,確定哈希值唯一性
	//才能做equals方法的判斷,這是SET集合中必須做的,確定不重複元素的存在
	public int hashCode()
	{
		return name.hashCode()+age*89;
	}
	
	//覆寫了hashCode()的方法之後,就在覆寫equals方法,主要都是為了確定元素唯一性
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Student))
			throw new ClassCastException("類型不比對");

		Student s=(Student)obj;

		//判斷同名同年齡的為一個學生,是以傳回值為false,最終就不會被加入到集合中!
		return this.name.equals(s.name) && this.age==age;
	}


	//實作Comparable接口,覆寫compareTo方法,這其實就是為了讓其自然排序
	public int compareTo(Student s)
	{
		//現根據年齡進行自然排序
		int num=new Integer(this.age).compareTo(new Integer(s.age));
		
		//當學生的年齡相同時,再進行名字的自然排序
		if (num==0)
		{
			return this.name.compareTo(s.name);
		}
		return num;
	}

	public String getName()
	{
		return name;
	}

	public int getAge()
	{
		return age;
	}
}

class StudentAddress3 
{
	public static void main(String[] args) 
	{
		//建立HashMap集合,把學生類和位址裝入進去!
		HashMap<Student,String> hm=new HashMap<Student,String>();
		hm.put(new Student("wangming",20),"huilixian");
		hm.put(new Student("wing",22),"sichuan");
		hm.put(new Student("wig",22),"xichang");
		hm.put(new Student("wg",23),"panzhihua");
		hm.put(new Student("wg",23),"moujjn");
		hm.put(new Student("abc",20),"nanjin");

		//通過keySet方法完成取出展示
		Set<Student> keySet=hm.keySet();
		Iterator<Student> is=keySet.iterator();

		sop("----keySet方法----");
		while (is.hasNext())
		{
			Student stu=is.next();
			String address=hm.get(stu);
			sop("姓名:"+stu.getName()+"年齡:"+stu.getAge()+"位址"+address);
		}

		//通過entrySet方法完成取出展示
		Set<Map.Entry<Student,String>> entrySet=hm.entrySet();
		Iterator<Map.Entry<Student,String>> iter=entrySet.iterator();

		sop("----entrySet方法----");
		while (iter.hasNext())
		{
			Map.Entry<Student,String> map=iter.next();
			Student stu=map.getKey();
			String address=map.getValue();
			sop("姓名:"+stu.getName()+"年齡:"+stu.getAge()+"位址:"+address);
		}

	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
           

五、【比較器的定義】中級應用!

/*
【重點】比較器
同樣之前一樣的題目要求,
現在隻是要按照學生的年齡排序,從年齡大到小的排序
*/

import java.util.*;
class Student implements Comparable<Student>
{
	private String name;
	private int age;
	
	Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	
	public void setName(String name)
	{
		this.name=name;
	}

	public String getName()
	{
		return name;
	}

	public void setAge(int age)
	{
		this.age=age;
	}

	public int getAge()
	{
		return age;
	}

	public int hashCode()
	{
		return name.hashCode()*age*89;
	}

	public boolean equals(Object obj)
	{
		if (!(obj instanceof Student))
		{
			throw new ClassCastException("類型不比對!");
		}
		
		Student s=(Student)obj;
		return this.name.equals(s.name) && this.age==s.age;
	}

	public int compareTo(Student s)
	{
		int num=new Integer(this.age).compareTo(new Integer(s.age));
		if (num==0)
		{
			return this.name.compareTo(s.name);
		}
		return num;
	}
}
/*
TreeMapTest4這個類可以自己試着分析,跟之前的一個執行個體的道理,并不是很難!
*/
class  TreeMapTest4
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> hm=new TreeMap<Student,String>(new myCompimpl());
		hm.put(new Student("wangkeze",28),"huilixian");
		hm.put(new Student("wangze",20),"huilixian");
		hm.put(new Student("wa",49),"huilixian");
		hm.put(new Student("wa",49),"huilixian");
		hm.put(new Student("a",49),"huilixian");

		//通過keySet方法完成取出展示
		Set<Student> hs=hm.keySet();
		Iterator<Student> itor=hs.iterator();
		while (itor.hasNext())
		{
			Student s=itor.next();
			String address=hm.get(s);
			sop(s.getName()+","+s.getAge()+":"+address);
		}

		//通過entrySet方法完成取出展示
		Set<Map.Entry<Student,String>> me=hm.entrySet();
		Iterator<Map.Entry<Student,String>> itorm=me.iterator();
		while (itorm.hasNext())
		{
			Map.Entry<Student,String> map=itorm.next();
			Student stu=map.getKey();
			String addressM=map.getValue();
			sop(stu.getName()+","+stu.getAge()+":"+addressM);
		}
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

/*
【分析】當我們具體的排序要求在集合中不能夠滿足時,我們就可以自定義一個比較器去完成!
下面就是一個比較器,我們來具體分析一下
*/

//自定義myCompimpl比較器名稱實作Comparator接口
class myCompimpl implements Comparator<Student>
{
	//要比較的對象都是傳入兩個學生類實體
	public int compare(Student s1,Student s2)
	{
		//通過這學生兩個實體提取各自的年齡進行compareTo方法的比較,再排序就行
		int num=new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		
		//如果兩個學生的年齡都是相同的,那麼再根據名稱的自然排序方式就行就OK了
		if (num==0)
		{
			return s1.getName().compareTo(s2.getName());
		}
		return num;
	}
}
           

六、進階應用:

/*
統計一個字元串中“每種字母出現的次數”,并且列印出來
列印的格式:x(幾次)、y(幾次)……

例如字元串:gfadgagkolauinaaf
【思路】
1.将字元串轉化成為字元數組,因為要對每一個字母進行操作
2.定義一個map集合,因為列印結果的字母有順序,是以要用到treemap集合
3.周遊字元數組
	将每一個字母作為健去查map集合,
	如果傳回為null,将該字元和1存入到map集合中,
	如果傳回不為null,說明該字元和對應的次數在集合中已經存在了,
	這時候,直接取出字元次數,自增之後再重新按照該健存入到集合中
*/
import java.util.*;
class GetCharNumber5
{
	public static void main(String[] args) 
	{
		String str="jfkl;ajf;lajfaljfl;afasfsadfds";
		getInfor(str);
	}

	public static void getInfor(String str)
	{
		//将字元串轉化成為字元數組
		char[] ch=str.toCharArray();

		//定義一個TreeMap集合,泛型類型分别是Character和Integer
		//因為存入集合中的引用是【字元】和【次數】
		TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
	
		//從字元數組中依次取出值到Map集合中判斷是否存在
		for (int i=0; i<ch.length;i++ )
		{
			//這裡是依次取出單個的字元到集合中去得到次數的值
			Integer value=tm.get(ch[i]);
			
			//如果Map中次數為空,那麼就說明沒有該字元存在,
			//于是加入該字元和次數1添加到集合中去,
			//這時出現的次數是第一次
			if (value == null)
			{
				tm.put(ch[i],1);
			}else 
			{
				//發現集合中的對應的該次數存在,那麼再加入相應的鍵值字元和+1之後的value
				//值到集合中去!
				value=value+1;
				tm.put(ch[i],value);
			}
		}
		
		/*這裡是entrySet方法,就不再一一介紹了,不難掌握的
		StringBuffer sb=new StringBuffer();
		Set<Map.Entry<Character,Integer>> setMap=tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it=setMap.iterator();
		
		while (it.hasNext())
		{
			Map.Entry<Character,Integer> me=it.next();
			Character key=me.getKey();
			Integer value=me.getValue();
			sb.append(key+"("+value+")"+"、");
		}

		sop(sb);
		*/
		
		//定義一個可變的容器來存儲要列印的内容……
		StringBuffer sb=new StringBuffer();
		
		//通過keySet方法去到Set集合中實作元素的疊代取出并且列印出來
		Set<Character> set=tm.keySet();
		Iterator<Character> it=set.iterator();
		while (it.hasNext())
		{
			Character key=it.next();
			Integer value=tm.get(key);

			//定義列印格式:很簡單的
			sb.append(key+"("+value+")"+"、");
		}
		sop(sb);	
	}
	
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
           

【總結】實作Map集合并不是很難,一定要抓住其特點,是一一映射存在的,很多問題都能迎刃而解!!

繼續閱讀