一: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集合并不是很難,一定要抓住其特點,是一一映射存在的,很多問題都能迎刃而解!!