第9天 集合
今日學習內容
Map集合
今日學習目標
可以說出Map集合特色
使用Map集合添加方法保存數據
使用」鍵找值」的方式遍歷Map集合
使用」鍵值對」的方式遍歷Map集合
可以使用HashMap存儲自定義鍵值對的數據
可以說出可變參數的做用
可以使用集合工具類
可以使用HashMap編寫鬥地主洗牌發牌案例
第1章 Map接口概述
1.1 Map集合的特色
咱們經過查看Map接口描述,發現Map接口下的集合與Collection接口下的集合,它們存儲數據的形式不一樣,以下圖。
Collection中的集合,元素是孤立存在的(理解爲單身),向集合中存儲元素採用一個個元素的方式存儲。
Map中的集合,元素是成對存在的(理解爲夫妻)。每一個元素由鍵與值兩部分組成,經過鍵能夠找對所對應的值。
Collection中的集合稱爲單列集合,Map中的集合稱爲雙列集合。
須要注意的是,Map中的集合不能包含重複的鍵,值能夠重複;每一個鍵只能對應一個值。
Map中經常使用的集合爲HashMap集合、LinkedHashMap集合。java
1.2 Map接口中經常使用集合概述
經過查看Map接口描述,看到Map有多個子類,這裏咱們主要講解經常使用的HashMap集合、LinkedHashMap集合。
HashMap:存儲數據採用的哈希表結構,元素的存取順序不能保證一致。因爲要保證鍵的惟1、不重複,須要重寫鍵的hashCode()方法、equals()方法。
LinkedHashMap:HashMap下有個子類LinkedHashMap,存儲數據採用的哈希表結構+鏈表結構。經過鏈表結構能夠保證元素的存取順序一致;經過哈希表結構能夠保證的鍵的惟1、不重複,須要重寫鍵的hashCode()方法、equals()方法。
注意:Map接口中的集合都有兩個泛型變量,在使用時,要爲兩個泛型變量賦予數據類型。兩個泛型變量的數據類型能夠相同,也能夠不一樣。
1.3 Map接口中的經常使用方法數組
Map接口的方法演示
public class MapDemo {
public static void main(String[] args) {
//建立Map對象
Map map = new HashMap();
//給map中添加元素
map.put("星期一", "Monday");
map.put("星期日", "Sunday");
System.out.println(map); // {星期日=Sunday, 星期一=Monday}工具
//當給Map中添加元素,會返回key對應的原來的value值,若key沒有對應的值,返回null System.out.println(map.put("星期一", "Mon")); // Monday System.out.println(map); // {星期日=Sunday, 星期一=Mon} //根據指定的key獲取對應的value String en = map.get("星期日"); System.out.println(en); // Sunday //根據key刪除元素,會返回key對應的value值 String value = map.remove("星期日"); System.out.println(value); // Sunday System.out.println(map); // {星期一=Mon} }
}學習
1.4 Map集合遍歷鍵找值方式
鍵找值方式:即經過元素中的鍵,獲取鍵所對應的值
操做步驟與圖解:
1.獲取Map集合中全部的鍵,因爲鍵是惟一的,因此返回一個Set集合存儲全部的鍵測試
代碼演示:
public class MapDemo {
public static void main(String[] args) {
//建立Map對象
Map map = new HashMap();
//給map中添加元素
map.put("鄧超", "孫儷");
map.put("李晨", "范冰冰");
map.put("劉德華", "柳巖");
//獲取Map中的全部key
Set keySet = map.keySet();
//遍歷存放全部key的Set集合
Iterator it =keySet.iterator();
while(it.hasNext()){
//獲得每個key
String key = it.next();
//經過key獲取對應的value
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
1.5 Entry鍵值對對象(補充一下內部類和內部接口)
在Map類設計時,提供了一個嵌套接口:Entry。Entry將鍵值對的對應關係封裝成了對象。即鍵值對對象,這樣咱們在遍歷Map集合時,就能夠從每個鍵值對(Entry)對象中獲取對應的鍵與對應的值。this
public class MapDemo {
public static void main(String[] args) {
//建立Map對象
Map map = new HashMap();
//給map中添加元素
map.put("鄧超", "孫儷");
map.put("李晨", "范冰冰");
map.put("劉德華", "柳巖");
//獲取Map中的全部key與value的對應關係
Set> entrySet = map.entrySet();
//遍歷Set集合
Iterator> it =entrySet.iterator();
while(it.hasNext()){
//獲得每一對對應關係
Map.Entry entry = it.next();
//經過每一對對應關係獲取對應的key
String key = entry.getKey();
//經過每一對對應關係獲取對應的value
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
注意:Map集合不能直接使用迭代器或者foreach進行遍歷。可是轉成Set以後就可使用了。
1.7 HashMap存儲自定義類型鍵值
練習1:使用map存儲:鍵爲學號,值爲一個學生的對象, 學生對象有屬性(姓名,年齡)
練習2:使用map存儲:鍵爲學生(姓名,年齡)值爲學生本身的家庭住址。那麼,既然有對應關係,則將學生對象和家庭住址存儲到map集合中。學生做 爲鍵, 家庭住址做爲值。
注意,學生姓名相同而且年齡相同視爲同一名學生。
學生類
public class Student {
private String name;
private int age;編碼
//編寫構造方法,文檔中已省略 //編寫get,set方法,文檔中已省略 //編寫toString方法,文檔中已省略
}
測試類
public class HashMapTest {
public static void main(String[] args) {
//1,建立hashmap集合對象。
Map map = new HashMap();spa
//2,添加元素。 map.put(new Student("lisi",28), "上海"); map.put(new Student("wangwu",22), "北京"); map.put(new Student("zhaoliu",24), "成都"); map.put(new Student("zhouqi",25), "廣州"); map.put(new Student("wangwu",22), "南京"); //3,取出元素。鍵找值方式 Set<Student> keySet = map.keySet(); for(Student key : keySet){ String value = map.get(key); System.out.println(key.toString()+"....."+value); } //取出元素。鍵值對方式 Set<Map.Entry<Student, String>> entrySet = map.entrySet(); for (Map.Entry<Student, String> entry : entrySet) { Student key = entry.getKey(); String value = entry.getValue(); System.out.println(key.toString()+"....."+value); } }
}
當給HashMap中存放自定義對象時,若是自定義對象做爲key存在,這時要保證對象惟一,必須複寫對象的hashCode和equals方法(若是忘記,請回顧HashSet存放自定義對象)。
若是要保證map中存放的key和取出的順序一致,可使用LinkedHashMap集合來存放。
1.8 LinkedHashMap
咱們知道HashMap保證成對元素惟一,而且查詢速度很快,但是成對元素存放進去是沒有順序的,那麼咱們要保證有序,還要速度快怎麼辦呢?
在HashMap下面有一個子類LinkedHashMap,它是鏈表和哈希表組合的一個數據存儲結構。設計
public class LinkedHashMapDmeo {
public static void main(String[] args) {code
LinkedHashMap<String, String> map = new LinkedHashMap<String,String>(); map.put("鄧超", "孫儷"); map.put("李晨", "范冰冰"); map.put("劉德華", "柳巖"); Set<Entry<String,String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) { System.out.println(entry.getKey()+" "+entry.getValue()); }
}
}
結果:
鄧超 孫儷
李晨 范冰冰
劉德華 柳巖
1.9 Properties類介紹
Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每一個鍵及其對應值都是一個字符串。
特色:
一、Hashtable的子類,map集合中的方法均可以用。
二、該集合沒有泛型。鍵值都是字符串。
三、它是一個能夠持久化的屬性集。鍵值能夠存儲到集合中,也能夠存儲到持久化的設備(硬盤、U盤、光盤)上。鍵值的來源也能夠是持久化的設備。
四、有和流技術相結合的方法。
代碼演示:
/*
public Object setProperty(String key, String value)調用 Hashtable 的方法 put。
public Set stringPropertyNames()返回此屬性列表中的鍵集,
public String getProperty(String key)用指定的鍵在此屬性列表中搜索屬性
*/
public class PropertiesDemo01 {
public static void main(String[] args) {
//建立集合對象
Properties prop = new Properties();
//添加元素到集合
//prop.put(key, value);
prop.setProperty("周迅", "張學友");
prop.setProperty("李小璐", "賈乃亮");
prop.setProperty("楊冪", "劉愷威");
//System.out.println(prop);//測試的使用 //遍歷集合 Set<String> keys = prop.stringPropertyNames(); for (String key : keys) { //經過鍵 找值 //prop.get(key) String value = prop.getProperty(key); System.out.println(key+"==" +value); }
}
}
1.10 讀取文件中的數據,並保存到集合
需求:從屬性集文件prop.properties 中取出數據,保存到集合中
分析:
1,建立集合
2,建立流對象
3,把流所對應文件中的數據 讀取到集合中
load(InputStream) 把指定流所對應的文件中的數據,讀取出來,保存到Propertie集合中
load(Reader)
4,關閉流
5,顯示集合中的數據
代碼演示:
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
//1,建立集合
Properties prop = new Properties();
//2,建立流對象
FileReader in = new FileReader("prop.properties");
//3,把流所對應文件中的數據 讀取到集合中
prop.load(in);
//4,關閉流
in.close();
//5,顯示集合中的數據
System.out.println(prop);
}
}
1.11 可變參數
在JDK1.5以後,若是咱們定義一個方法須要接受多個參數,而且多個參數類型一致,咱們能夠對其簡化成以下格式:
修飾符 返回值類型 方法名(參數類型… 形參名){ }
其實這個書寫徹底等價與
修飾符 返回值類型 方法名(參數類型[] 形參名){ }
只是後面這種定義,在調用時必須傳遞數組,而前者能夠直接傳遞數據便可。
jdk1.5之後。出現了簡化操做。… 用在參數上,稱之爲可變參數。
一樣是表明數組,可是在調用這個帶有可變參數的方法時,不用建立數組(這就是簡單之處),直接將數組中的元素做爲實際參數進行傳遞,其實編譯成的class文件,將這些元素先封裝到一個數組中,在進行傳遞。這些動做都在編譯.class文件時,自動完成了。
代碼演示:
public class ParamDemo {
public static void main(String[] args) {
int[] arr = {21,89,32};
int sum = add(arr);
System.out.println(sum);
sum = add(21,89,32);//可變參數調用形式
System.out.println(sum);
} //JDK1.5以後寫法 public static int add(int...arr){ int sum = 0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } //原始寫法 /* public static int add(int[] arr) { int sum = 0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } */
}
上述add方法在同一個類中,只能存在一個。由於會發生調用的不肯定性
注意:
1,一個方法中只能有一個可變參數.
2這個方法擁有多參數,參數中包含可變參數,可變參數必定要寫在參數列表的末尾位置。
1.12 Collections集合工具類(可補充靜態導入和Map嵌套)
Collections是集合工具類,用來對集合進行操做。部分方法以下:
public static void shuffle(List list) // 集合元素存儲位置打亂
//list集合元素 [11,33,55,77]
Collections.shuffle( list );
//使用shuffle方法後,集合中的元素爲[77,33,11,55],每次執行該方法,集合中存儲的元素位置都會隨機打亂
第2章 模擬鬥地主洗牌發牌
2.1 案例介紹
按照鬥地主的規則,完成洗牌發牌的動做。
具體規則:
1. 組裝54張撲克牌
2.2 案例需求分析
準備牌:
完成數字與紙牌的映射關係:
使用雙列Map(HashMap)集合,完成一個數字與字符串紙牌的對應關係(至關於一個字典)。
洗牌:
經過數字完成洗牌發牌
發牌:
將每一個人以及底牌設計爲ArrayList,將最後3張牌直接存放於底牌,剩餘牌經過對3取模依次發牌。
存放的過程當中要求數字大小與鬥地主規則的大小對應。
將表明不一樣紙牌的數字分配給不一樣的玩家與底牌。
看牌:
經過Map集合找到對應字符展現。
經過查詢紙牌與數字的對應關係,由數字轉成紙牌字符串再進行展現。
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; /* * 鬥地主洗牌發牌排序 */ public class Poker { public static void main(String[] args) { //準備花色 ArrayList<String> color = new ArrayList<String>(); color.add("♠"); color.add("♥"); color.add("♦"); color.add("♣"); //準備數字 ArrayList<String> number = new ArrayList<String>(); Collections.addAll(number,"3","4","5","6","7","8","9","10","J","Q","K","A","2"); //定義一個map集合:用來將數字與每一張牌進行對應 HashMap<Integer, String> map = new HashMap<Integer, String>(); int index = 0; //加入大小王 map.put(index++, "小☺"); map.put(index++, "大☻"); for (String thisNumber : number) { for (String thisColor : color) { map.put(index++, thisColor+thisNumber); } } //一副54張的牌 ArrayList裏邊爲0-53的數的新牌 ArrayList<Integer> cards = new ArrayList<Integer>(); for (int i = 0; i <= 53; i++) { cards.add(i); } //洗牌 Collections.shuffle(cards); //建立三個玩家和底牌 ArrayList<Integer> iPlayer = new ArrayList<Integer>(); ArrayList<Integer> iPlayer2 = new ArrayList<Integer>(); ArrayList<Integer> iPlayer3 = new ArrayList<Integer>(); ArrayList<Integer> itCards = new ArrayList<Integer>(); //遍歷這副洗好的牌,遍歷過程當中,將牌發到三個玩家和底牌中 for (int i = 0; i < cards.size(); i++) { if(i>=51) { iCards.add(cards.get(i)); } else { if(i%3==0) { iPlayer.add(cards.get(i)); }else if(i%3==1) { iPlayer2.add(cards.get(i)); }else { iPlayer3.add(cards.get(i)); } } } //對每一個人手中的牌排序 Collections.sort(iPlayer); Collections.sort(iPlayer2); Collections.sort(iPlayer3); //對應數字形式的每一個人手中的牌,定義字符串形式的牌 ArrayList<String> sPlayer = new ArrayList<String>(); ArrayList<String> sPlayer2 = new ArrayList<String>(); ArrayList<String> sPlayer3 = new ArrayList<String>(); ArrayList<String> sCards = new ArrayList<String>(); for (Integer key : iPlayer) { sPlayer.add(map.get(key)); } for (Integer key : iPlayer2) { sPlayer2.add(map.get(key)); } for (Integer key : iPlayer3) { sPlayer3.add(map.get(key)); } for (Integer key : iCards) { sCards.add(map.get(key)); } //看牌 System.out.println(sPlayer); System.out.println(sPlayer2); System.out.println(sPlayer3); System.out.println(sCards); } }