2017 - 10 -24 集合框架 Map HashMap TreeMap HashMap嵌套

1 Map
  作爲學生來說,是根據學號來區分不同的學生的,那麼假設我現在已經知道了學生的學號,我要根據學號去獲取學生姓名,請問怎麼做呢?
  如果採用前面講解過的集合,我們只能把學號和學生作爲一個對象的成員,然後存儲整個對象,將來遍歷的時候,判斷,獲取對應的名稱。
  但是,如果我都能把學生姓名拿出來了,我還需要根據編號去找嗎?
  針對我們目前的這種需求,僅僅知道學號,就想知道學生姓名的情況,java就提供了一種新的集合 Map
  通過查看API,我們知道Map集合的一個最大的特點,就是它可以存儲鍵值對的元素,這個時候存儲我們上面的需求,就可以這樣做
    學號1         姓名1
    學號2         姓名2
    學號3         姓名3
    學號2(不行)   姓名4
    學號4         姓名4

Map集合的特點:
  將鍵映射到值得對象,一個映射不能包含重複的鍵:每個鍵最多隻能映射到一個值。
Map集合和Collection集合的區別?
  Map集合存儲元素是成對出現的,Map集合的鍵是唯一的,值是可重複的。可以把這個理解爲:夫妻對。
  Collection集合存儲元素是單獨出現的,Collection的兒子Set是唯一的,List是可重複的,可以把這個理解爲:光棍。      
注意:
Map集合的數據結構值針對鍵有效,跟值無關
Collection集合的數據結構是針對元素有效

HashMap,TreeMap

2 Map集合的功能概述
(1)添加功能
     V put(K key,V value):添加元素。這個其實還有另一個功能,先不講。
           如果鍵是第一次存儲,就直接存儲元素,返回null 
           如果鍵不是第一次存在,就用值把以前的值替換掉,返回以前的值
(2)刪除功能
     void clear():移除所有的鍵值對元素
     V remove(Object key):根據鍵刪除鍵值對元素,並把值返回
(3)判斷功能
     boolean containsKey(Object key):判斷集合是否包含指定的鍵
     boolean containsValue(Object value):判斷集合是否包含指定的值
     boolean isEmpty():判斷集合是否爲空
(4)獲取功能
     Set<Map.Entry<E,V>> entrySet():???
     V get(Object key):根據鍵獲取值
     Set<E> keySet():獲取集合中所有鍵的集合
     Collection<V> values():獲取集合中所有值得集合
(5)長度功能
     int size():返回集合中的鍵值對的對數
---------------------------------------------
     //創建集合對象
     Map<String,String> m = new HashMap<String,String>();
     //添加元素
     //V put(K key,V value):添加元素。這個其實還有另一個功能,先不講。   
     System.out.println("put:"+m.put("學號1","學生1"));
     System.out.println("put:"+m.put("學號1","學生2"));
     //輸出集合名稱
     System.out.println("map:"+map);
     //輸出: put:null 
                    put:學生1
                    map:{學號1=學生2}
----------------------------------------------------------
     //創建集合對象
     Map<String,String> m = new HashMap<String,String>();
     //添加元素
     map.put("學號1","學生1");
     map.put("學號2","學生2");
     map.put("學號3","學生3");
     //輸出集合名稱
     //System.out.println("map:"+map);
     //輸出:map:{學號1=學生2,學號3=學生3,學號2=學生2} //無序
      
     System.out.println("remove:"+map.remove("學號1"));  
     System.out.println("remove:"+map.remove("學號1"));
     //輸出: remove:學生1
              remove:null
              map:{學號3=學生3,學號2=學生2}

3 Map 獲取功能
     Set<Map.Entry<E,V>> entrySet():???
     V get(Object key):根據鍵獲取值
     Set<E> keySet():獲取集合中所有鍵的集合
     Collection<V> values():獲取集合中所有值得集合
-----------------------------------------------------------
     //創建集合對象
     Map<String,String> m = new HashMap<String,String>();
     //添加元素
     map.put("學號1","學生1");
     map.put("學號2","學生2");
     map.put("學號3","學生3");
     // V get(Object key):根據鍵獲取值
     System.out.println("get:"+map.get("學號1"));
     //輸出:  get:學生1

     //Set<E> keySet():獲取集合中所有鍵的集合
     Set<String> set = map.keySet();
     for(String key : set){
           System.out.println(key);
       }
     //輸出:  學號1
               學號2
               學號3
       
     //  Collection<V> values():獲取集合中所有值得集合
     Collection<String> con = map.values();
     for(String value : con){
            System.out.println(value);
         }
     //輸出:  學生1
               學生2
               學生3

4 Map 集合的遍歷
(1)  //創建集合對象
     Map<String,String> m = new HashMap<String,String>();
     //添加元素
     map.put("學號1","學生1");
     map.put("學號2","學生2");
     map.put("學號3","學生3");
     //遍歷
     //獲取所有的鍵
     Set<String> set = map.keySet();
     //遍歷集合的鍵,獲取得到每一個鍵
     for(String key : set){
           //根據鍵去找值
           String value = map.get(key) ;
           System.out.println(key+"---"+value);
       }

(2)  
A:獲取所有鍵值對對象的集合
B:遍歷鍵值對對象的集合,得到每一個鍵值對對象
C:根據鍵值對對象獲取鍵和值
這裏麻煩的是鍵值對對象如何表示呢?
     看看我們開始的一個方法:
      Set<Map.Entry<E,V>> entrySet():返回的是鍵值對對象的集合

     //創建集合對象
     Map<String,String> m = new HashMap<String,String>();
     //添加元素
     map.put("學號1","學生1");
     map.put("學號2","學生2");
     map.put("學號3","學生3");
     //獲取所有鍵值對對象的集合
     Set<Map.Entry<String,String>> set = map.entrySet();
     //遍歷鍵值對對象的集合,得到每一個鍵值對對象
     for(Map.Entry<String,String> me : set){
             //根據鍵值對對象獲取鍵和值
             String key = me.getKey();
             String value = me.getValue();
             System.out.println(key + "---" + value);
       }
     //輸出:   學號1---學生1
                      學號2---學生2
                      學號3---學生3

(3) 兩種方式的圖解



5 HashMap
  HashMap:是基於哈希表的Map接口實現。
  哈希表的作用是用來保證鍵的唯一性的。
----------------------------------------------------
(1)HashMap<String,String>
     //創建集合對象
     HashMap<String,String> hm = new HashMap<String,String>();
     //創建元素並添加元素
     hm.put("it001","馬雲");
     hm.put("it002","馬化騰");
     hm.put("it003","喬布斯");
     hm.put("it004","張朝陽");
     hm.put("it001","馬雲2"); //覆蓋掉馬雲 保證唯一性
     //遍歷
     Set<String> set = hm.keySet();
     for(String key : set){
             String value = hm.get(key);
             System.out.println(key + "---" +value);
       }
-----------------------------------------------------
(2)HashMap<Integer,String>
     //創建集合對象
     HashMap<Integer,String> hm = new HashMap<Integer,String>();
     //創建元素並添加元素
     hm.put(1,"馬雲");
     hm.put(2,"馬化騰");
     hm.put(3,"喬布斯");
     hm.put(4,"張朝陽");
     //下面的寫法是八進制,但是不能出現8以上的單個數據
     //hm.put(001,"hello"); //不報錯
     //hm.put(005,"hello"); //不報錯
     //hm.put(008,"hello"); //報錯
     //遍歷
     Set<Integer> set = hm.keySet();
     for(Integer key : set){
             String value = hm.get(key);
             System.out.println(key + "---" +value);
       }
-------------------------------------------------------
(3) HashMap<String,Student>

     //創建集合對象
     HashMap<String,Student> hm = new HashMap<String,Student>();
     //創建學生對象
     Student s1 = new Student("學生1",15);
     Student s2 = new Student("學生2",15);
     Student s3 = new Student("學生3",15);
     Student s4 = new Student("學生4",15);
     //添加元素
     hm.put("957",s1);
     hm.put("958",s2);
     hm.put("959",s3);
     hm.put("960",s4);
     //遍歷
     Set<String> set = hm.keySet();
     for(String key : set){
        //注意了:這次值不是字符串了
        //String value = hm.get(key);
        Student value = hm.get(key);
        System.out.println(key+"---"+value.getName()+"---"+value.getAge());
        }
      //輸出:
             957---學生1---15
             958---學生2---15
             959---學生3---15
             960---學生4---15
---------------------------------------------------------
(4) HashMap<Student,String>
鍵:Student
       要求:如果兩個對象的成員變量值都相同,則爲同一個對象
值:String
       
     //創建集合對象
     HashMap<Student,String> hm = new HashMap<Student,String>();
     //創建學生對象
     Student s1 = new Student("學生1",15);
     Student s2 = new Student("學生2",15);
     Student s3 = new Student("學生3",15);
     Student s4 = new Student("學生4",15);
     Student s4 = new Student("學生4",15);
     //添加元素
     hm.put(s1,"957");
     hm.put(s2,"958");
     hm.put(s3,"959");
     hm.put(s4,"960");
     hm.put(s4,"961");
     //遍歷
     Set<Student> set = hm.keySet();
     for(Student key : set){    
        String value = hm.get(key);
        System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
  }
     //輸出:
            學生1---15---957
            學生2---15---958
            學生3---15---959
            學生4---15---960
            學生4---15---961
      //因爲HashMap 底層是Hash  依賴於equals和hashCode
      //需要在學生類中重寫 equals類即可。

6 LinkedHashMap
    是Map接口的哈希表和鏈表實現,具有可預知的迭代順序
    由哈希表保證鍵的唯一性
    由鏈表保證鍵類的有序(存儲和取出的順序一致)

  import java.util.LinkedHashMap;
  import java.util.Set;
    //創建集合對象
    LinkedHashMap<String,String> hm = new LinkedHashMap<String,String>();
    //創建並添加元素
    hm.put("1","hello");
    hm.put("2","world");
    hm.put("3","java");
    hm.put("4","javaee");
    hm.put("4","javaeeee");
    //遍歷
     Set<String> set = hm.keySet();
     for(String key : set){
             String value = hm.get(key);
             System.out.println(key + "---" +value);
       }
     //輸出:
             1---hello 
             2---world
             3---java
             4---javaeeee

7 TreeMap
   是基於紅黑樹的Map接口的實現。
------------------------------------------------------------
    //創建集合對象
    TreeMap<String,String> tm = new TreeMap<String,String>();
    //創建並添加元素
    tm.put("1","hello");
    tm.put("2","world");
    tm.put("3","java");
    tm.put("4","javaee");
    tm.put("4","javaeeee");
    //遍歷
     Set<String> set = tm.keySet();
     for(String key : set){
             String value = tm.get(key);
             System.out.println(key + "---" +value);
       }
    //輸出(自然排序):
             1---hello 
             2---world
             3---java
             4---javaeeee
-------------------------------------------------------------
     //創建集合對象
     TreeMap<Student,String> tm = new TreeMap<Student,String>();
     //創建學生對象
     Student s1 = new Student("學生1",15);
     Student s2 = new Student("學生2",15);
     Student s3 = new Student("學生3",15);
     Student s4 = new Student("學生4",15);
     Student s4 = new Student("學生4",15);
     //添加元素
     tm.put(s1,"957");
     tm.put(s2,"958");
     tm.put(s3,"959");
     tm.put(s4,"960");
     tm.put(s4,"961");
     //遍歷
     Set<Student> set = tm.keySet();
     for(Student key : set){    
        String value = tm.get(key);
        System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
  }
      //會報錯   因爲沒有給定排序
-----------------------比較器排序----------------------
      //創建集合對象
     TreeMap<Student,String> tm = new TreeMap<Student,String>(
                new Comparator<Student>(){
                    @Override
                public int compare(Student s1 , Student s2){
                    //主要條件
                    int num = s1,getAge() - s2.getAge();
                    //次要條件
                    int num2 = num == 0 ? s1.getName().compareTo(                                     s2.getName()) :num ;
                    return num ;
               }
}
);

8 練習:統計字符串中每個字符串出現的次數
要求:"aaaabbbcccdd"  結果:a(4)b(3)c(3)d(2)

  //定義一個字符串(可以改進爲鍵盤錄入)
  Scanner sc = new Scanner(System.in);
  System.out.println("請輸入一個字符串:");
  String line = sc.nextLine();
  //定義一個TreeMap的集合
  TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
  //把字符串轉爲字符數組
  char[] chs = line.toCharArray();
  //遍歷字符數組,得到每一個字符
  for(char ch : chs){
     //拿剛纔得到的字符作爲鍵到集合中去找值,看返回值
     Integer i = tm.get(ch);
     //是null:說明該鍵不存在,就把該字符作爲鍵,1作爲值存儲
     if(i == null){
         tm.put(ch,1);
  }else{
     //不是null:說明該鍵存在,就把值加1,然後重寫存儲該鍵和值
         i++;
         tm.put(ch,i);
       }
 }
      //定義字符串緩衝區變量
      StringBuilder sb = new StringBuilder();
      //遍歷集合,得到鍵和值,進行按照要求拼接
      Set<Character> set = tm.keySet();
      for(Character key : set){
                   Integer value = tm.get(key);
                   sb.append(key).append("(").append(value).append(")");
 }
      //把字符串緩衝區轉換成字符串輸出
      String result = sb.toString();
      System.out.println("result:"+result);
     
9 HashMap 集合嵌套HashMap
  //創建集合對象
  HashMap<String,HashMap<String,Integer>> bigMap = new HashMap<String,HashMap<String,Integer>>;
  //創建小班集合對象
  HashMap<String,Integer> smallMap = new HashMap<String,Integer>();
  //添加元素
  smallMap.put("小班學生1",20); 
  smallMap.put("小班學生2",22); 
  smallMap.put("小班學生3",21); 
  smallMap.put("小班學生4",20);
  //把小班加到大集合中
  bigMap.put("small",smallMap);
  
  //創建小班2集合對象
  HashMap<String,Integer> small2Map = new HashMap<String,Integer>();
  //添加元素
  small2Map.put("小班2學生1",20); 
  small2Map.put("小班2學生2",22); 
  small2Map.put("小班2學生3",21); 
  small2Map.put("小班2學生4",20);
  //把小班2加到大集合中
  bigMap.put("small2",small2Map);
  
  //遍歷集合
  Set<String> bigMapSet = bigMap.keySet();
  for(String bigMapKey : bigMapSet){
         System.out.println(bigMapKey);
          HashMap<String,Integer> bigMapValue = bigMap.get(bigMapKey);
          Set<String> bigMapValueSet = bigMapValue.keySet();
           for(String bigMapValueKey : bigMapValueSet){
              Integer bigMapValueValue = bigMapValue.get(bigMapValueKey);
                System.out.println(bigMapValueKey+"---"+bigMapValueValue);
     }
 }

10 HashMap 嵌套 ArrayList
   //創建集合對象
   HashMap<String,ArrayList<String>> hm = now HashMap<String,ArrayList<String>>();
   //創建元素集合1
   ArrayList<String> array1 = new ArrayList<String>();
   array1.add("呂布");
   arrayl.add("周瑜");
   hm.put("三國演義",array1);

   //創建元素集合2
   ArrayList<String> array2 = new ArrayList<String>();
   array1.add("令狐沖");
   arrayl.add("林平之");
   hm.put("笑傲江湖",array2);

   //創建元素集合3
   ArrayList<String> array3 = new ArrayList<String>();
   array1.add("郭靖");
   arrayl.add("楊過");
   hm.put("神鵰俠侶",array3);

   //遍歷集合
   Set<String> set = hm.keySet();
   for(String key : set){
           System.out.println(key);
            ArrayList<String> value = hm.get(key);
            for(String s : value){
                 System.out.println(s);
        }
 }
  //輸出
             三國演義
                            呂布
                            周瑜
             笑傲江湖     
                            令狐沖
                            林平之
             神鵰俠侶
                            郭靖
                            楊過


11 ArrayList 嵌套 HashMap
   //創建集合對象
   ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String,String>>();
   //創建元素1
   HashMap<String,String> hm1 = new HashMap<String,Stirng>();
   hm1.put("周瑜","小喬");
   hm1.put("呂布","貂蟬");
   //把元素添加到array裏面
   array.add(hm1);

   //創建元素2
   HashMap<String,String> hm2 = new HashMap<String,Stirng>();
   hm2.put("郭靖","黃蓉");
   hm2.put("楊過","小女龍");
   //把元素添加到array裏面
   array.add(hm2);

   //創建元素1
   HashMap<String,String> hm3 = new HashMap<String,Stirng>();
   hm3.put("令狐沖","任盈盈");
   hm3.put("林平之","嶽靈珊");
   //把元素添加到array裏面
   array.add(hm3);

   //遍歷
   for(HashMap<String,String> hm : array){
            set<String> set = hm.keySet();
            for(String key : set){
                 String value = hm.get(key);
                  System.out.println(key +"---"+value);
                }
       }

12 三層嵌套
     //創建大集合
     HashMap<String,HashMap<String,ArrayList<Student>>> czbkMap = new HashMap<String,HashMap<String,ArrayList<Student>>>();
     //北京校區數據
     HashMap<String,ArrayList<Student>> bjCzbkMap = new HashMap<String,ArrayList<Student>>;
     ArrayList<Student> array1 = ArrayList<Student>();
     Student s1 = new Student("林青霞",27);
     Sutdent s2 = new Student("風清揚",30);
     array1.add(s1);
     array1.add(s2);
     ArrayList<Student> array2 = ArrayList<Student>();  
     Student s3 = new Student("趙雅芝",27);
     Sutdent s4 = new Student("武鑫",30);
     array2.add(s3);
     array2.add(s4);
     bjCzbkMap.put("基礎班",array1);
     bjCzbkMap.put("就業班",array2);
     czbkMap.put("北京校區",bjCzbkMap);
     
     //西安校區數據     
     HashMap<String,ArrayList<Student>> xaCzbkMap = new HashMap<String,ArrayList<Student>>;
     ArrayList<Student> array3 = ArrayList<Student>();
     Student s5 = new Student("范冰冰",27);
     Sutdent s6 = new Student("劉毅",30);
     array3.add(s5);
     array3.add(s6);
     ArrayList<Student> array4 = ArrayList<Student>();  
     Student s7 = new Student("李冰冰",27);
     Sutdent s8 = new Student("張志豪",30);
     array4.add(s7);
     array4.add(s8);
     xaCzbkMap.put("基礎班",array3);
     xaCzbkMap.put("就業班",array4);
     czbkMap.put("西安校區",xaCzbkMap);

     //遍歷集合
     Set<Stirng> czbkMapSet = czbkMap.keySet();
     for(String czbkMapKey : czbkMapSet){
              System.out.println(czbkMapKey);
         HashMap<String,ArrayList<Student>> czbkMapValue = czbkMap.get(czbkMapKey);
         Set<String> czbkMapValueSet =czbkMapValue.keySet();
         for(String czbkMapValueKey : czbkMapValueSet){
                  ArrayList<Student> czbkMapValueValue = czbkMapValue.get(czbkMapValueKey);
         for(Student s : czbkMapValueValue){
               System.out.println("\t"+s.getName()+"\t"+s.getAge());
               }
      }
 }

13 Hashtable 和HashMap 的區別
   Hashtable:線程安全,效率低,不允許你null鍵和null值
   Hashmap:線程不安全,效率高,允許null 鍵和null值

   List,Set,Map等接口是否都繼承自Map接口
   List,Set不是繼承自Map接口,它們繼承自Collection接口
   Map接口本身就是一個頂層接口  

14 Collections
    是針對集合進行操作的工具類,都是靜態方法
  面試題:
   Collection和Collections的區別?
     Collection:是單列集合的頂層接口,有子接口List和Set。
     Collections:是針對集合操作的工具類,有隊集合進行排序和二分查找的方法。

public static <T> void sort(List<T> list) : 排序 默認情況下是自然排序
public static <T> int binarySearch(List<?> list,T key) :二分查找
public static <T> T max(Collection<?> coll) : 最大值
public static void reverse(List<?> list) :反轉
public static void shuffle(List<?> list) :隨機置換

15 ArrayList存儲自定義對象並排序

  //創建集合對象
   List<Student> list = new ArrayList<Student>();
   //創建元素
   Student s1 = new Student("nihao",27);
   Student s2 = new Student("hello",26);
   Student s3 = new Student("world",28);
   Student s4 = new Student("java",20);
   Student s5 = new Student("javaee",20);
   //添加元素
   list.add(s1);
   list.add(s2);
   list.add(s3);
   list.add(s4);
   list.add(s5);
   //自然排序
   //Collection.sort(list);
   //比較器排序 如果同時有自然排序和比較器排序,以比較器排序爲主
   Collection.sort(list,new Comparator<Student>(){
         @Override
    public int compareTo(Student s){
         int num = this.age - s.age;
         int num2 = num == 0 ? this.name.compareTo(s.name) : num;
         return num2;
          }
);
   //遍歷集合
   for(Student s : ts){
         System.out.println(s.getName()+"---"+s.getAge());
    }
   //輸出: java---20
            javaee---20
            hello---26
            nihao---27
            world---28

 //自然排序 需要在Student類中重寫
 public class Student implements Comparable<Student>{
      ......
          @Ovrride
    public int compareTo(Student s){
         int num = this.age - s.age;
         int num2 = num == 0 ? this.name.compareTo(s.name) : num;
         return num2;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章