Java基礎—集合框架(三)

集合框架(三)

一、Map集合

    1.概述
      Map集合用於存儲鍵值對,且它保證鍵的唯一性,並且每個鍵最多隻能映射一個值。Map集合是Set集合的底層實現,其和Collection在集合框架中並列存在。

    2.Map集合共性方法
      1)添加操作

-V put(K key, V value):添加指定的鍵值對
-void putAll(Map<? extends K, ? extends V>, m):添加指定Map集合

注意:
put()會返回該鍵對應的被覆蓋的值
第一次存儲put(“01”, “zhangsan”);返回null;”01”鍵對應的被覆蓋的值爲null;
第二次存儲put(“01”, “wangwu”);返回”zhangsan”;”01”鍵對應的被覆蓋的值爲”zhangsan”;

      2)刪除操作

-void clear():清楚所有映射關係
-V remove(Object key):根據鍵刪除映射值

      3)判斷操作

-boolean containsKey(Object key):判斷是否包含指定鍵的映射關係
-boolean containsValue(Object value):判斷是否包含指定值的映射關係
-boolean isEmpty():判斷是否爲空

      4)獲取操作

-V get(Object Key):通過鍵獲得值
-int size():獲取Map長度
-Collection values():返回所有的映射的值
-Set entrySet():返回包含的映射關係
-Set keySet():返回包含的鍵

    3.Map集合子類

  • Map
    • HashTable
    • HashMap
    • TreeMap

      1)HashTable
        HashTable底層是哈希表數據結構。此類實現一個哈希表,該哈希表將鍵映射到相應的值上。任何非null的對象都可以做鍵或值。爲了成功在哈希表中存儲和獲取對象,用作鍵的對象必須實現hashCode()方法和equals()方法。HashTable類是線程同步的。

      2)HashMap
        HashMap底層是哈希表數據結構。此類與HashTable大致相同,但允許使用null的對象作爲鍵或值。HashMap不保證映射的順序,特別是它不保證該順序恆久不變。HashMap類是線程不同步的,效率高於HashTable

      3)TreeMap
        TreeMap底層是二叉樹數據結構。此類可以實現爲Map集合中的鍵排序。TreeMap線程不同步。

    4.Map集合方法應用
      演示Map集合基本方法。

示例代碼:

package com.heisejiuhuche.Collection;

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> hm = new HashMap<String, String>();

        /* 添加操作 */
        hm.put("01", "java01");
        hm.put("02", "java02");
        hm.put("03", "java03");
        hm.put("04", "java04");

        System.out.println(hm);

        /* 清空Map集合 */
        hm.clear();
        /* 刪除04鍵及其值 */
        hm.remove("04");
        System.out.println(hm);

        /* Map中是否包含指定鍵或值 */
        System.out.println(hm.containsKey("02"));
        System.out.println(hm.containsValue("java03"));

        /* 通過鍵獲取值 */
        System.out.println(hm.get("01"));
        /* 獲取Map長度 */
        System.out.println(hm.size());

        Collection<String> c = hm.values();

        for(String str : c) {
            System.out.println("Collection: " + str);
        }
    }
}

程序輸出結果:

{01=java01, 02=java02, 03=java03, 04=java04}
{01=java01, 02=java02, 03=java03}
true
true
java01
3
Collection: java01
Collection: java02
Collection: java03

    5.Map集合元素取出方式
      1)keySet()方法
        Map中所有的key存入Set集合,再通過Set集合的迭代器將所有key取出,最後通過get()方法獲取每個key的對應值。

示例代碼:

package com.heisejiuhuche.Collection;

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

public class MapDemo {
    public static void main(String[] args) {
        keySet();
        entrySet();
    }

    private static void keySet() {
        Map<String, String> hm = new HashMap<String, String>();

        hm.put("01", "java01");
        hm.put("02", "java02");
        hm.put("03", "java03");
        hm.put("04", "java04");

        for(Iterator<String> it = hm.keySet().iterator(); it.hasNext(); ) {
            String key = it.next();
            System.out.println(key + "::" + hm.get(key));
        }
    }
}

程序輸出結果:

01::java01
02::java02
03::java03
04::java04

      2)entrySet()方法
        Map集合中的映射關係存入到Set集合中。該關係的數據類型是Map.Entry

示例代碼:

package com.heisejiuhuche.Collection;

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

public class MapDemo {
    public static void main(String[] args) {
        keySet();
        entrySet();
    }

    private static void entrySet() {
        Map<String, String> hm = new HashMap<String, String>();

        hm.put("01", "java01");
        hm.put("02", "java02");
        hm.put("03", "java03");
        hm.put("04", "java04");

        for(Iterator<Map.Entry<String, String>> it = hm.entrySet().iterator();  it.hasNext(); ) {
            Map.Entry<String, String> me = it.next();
            System.out.println(me.getKey() + "-----" + me.getValue());
        }
    }
}

程序輸出結果:

01-----java01
02-----java02
03-----java03
04-----java04

這裏寫圖片描述

高能:
Map.Entry中的Entry,是一個接口。它是Map接口中的內部接口。示例代碼:

interface Map {
    public static interface Entry {
        public abstract Object getKey();
        public abstract Object getValue();
    }
}

    6.Map練習
      1)練習1
        每一個學生有對應的歸屬地,用Map集合存儲學生Student,地址String。學生的屬性有姓名,年齡。當姓名和年齡相同時視爲同一學生,保證學生唯一性。

示例代碼:

package com.heisejiuhuche.Collection;

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

public class MapTest {
    public static void main(String[] args) {
        Map<MyStudent, String> m = new HashMap<MyStudent, String>();

        m.put(new MyStudent("lisi01", 12), "beijing"); 
        m.put(new MyStudent("lisi03", 14), "shanghai"); 
        m.put(new MyStudent("lisi03", 14), "hangzhou"); 
        m.put(new MyStudent("lisi04", 15), "chengdu"); 
        m.put(new MyStudent("lisi02", 13), "shenzhen"); 

        /*
         * keySet()取出
         */
        for(Iterator<MyStudent> it = m.keySet().iterator(); it.hasNext(); ) {
            MyStudent stu = it.next();
            System.out.println(stu.toString() + "------" + m.get(stu));
        }

        /*
         * entrySet()取出 
         */
        for(Iterator<Map.Entry<MyStudent, String>> iter = m.entrySet().iterator(); iter.hasNext(); ) {
            Map.Entry<MyStudent, String> me = iter.next();
            MyStudent stu = me.getKey();
            String str = me.getValue();
            System.out.println(stu.toString() + "::" + str);
        }
    }
}

class MyStudent implements Comparable<MyStudent> {
    private String name;
    private int age;

    MyStudent(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    /*
     * 複寫compareTo方法,確保存入二叉樹數據結構中有比較性
     */
    public int compareTo(MyStudent stu) {
        int num = new Integer(this.age).compareTo(new Integer(stu.age));

        if(num == 0) {
            return this.name.compareTo(stu.name);
        }

        return num;
    }

    /*
     * 複寫hashCode方法,確保鍵的唯一性
     */
    public int hashCode() {
        return this.name.hashCode() + this.age * 37;
    }

    /*
     * 複寫equals方法,確保鍵的唯一性
     */
    public boolean equals(Object obj) {
        if(!(obj instanceof MyStudent)) {
            throw new ClassCastException("Class not match...");
        }
        MyStudent stu = (MyStudent)obj;
        return this.name.equals(stu.name) && this.age == stu.age;
    }

    public String toString() {
        return this.name + "===" + this.age;
    }
}

程序輸出結果:

lisi03===14------hangzhou
lisi01===12------beijing
lisi04===15------chengdu
lisi02===13------shenzhen
lisi03===14::hangzhou
lisi01===12::beijing
lisi04===15::chengdu
lisi02===13::shenzhen

      2)練習2
        對學生對象的姓名進行升序排序。

示例代碼(MyStudent類同上):

package com.heisejiuhuche.Collection;

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

public class TreeMapTest {
    public static void main(String[] args) {
        Map<MyStudent, String> tm = new TreeMap<MyStudent, String>(new MyComparator());

        tm.put(new MyStudent("alisi03", 14), "shanghai"); 
        tm.put(new MyStudent("blisi03", 14), "hangzhou"); 
        tm.put(new MyStudent("dlisi04", 15), "chengdu"); 
        tm.put(new MyStudent("lisi02", 13), "shenzhen"); 
        tm.put(new MyStudent("lisi01", 12), "beijing"); 

        for(Iterator<Map.Entry<MyStudent, String>> it = tm.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<MyStudent, String> me = it.next();
            MyStudent stu = me.getKey();
            String str = me.getValue();
            System.out.println(stu.toString() + "***" + str);
        }
    }
}

class MyComparator implements Comparator<MyStudent> {
    public int compare(MyStudent s1, MyStudent s2) {
        int num = s1.getName().compareTo(s2.getName());

        if(num == 0) {
            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
        }

        return num;
    }
}

聲明瞭比較器,按姓名排序。程序輸出結果:

alisi03===14***shanghai
blisi03===14***hangzhou
dlisi04===15***chengdu
lisi01===12***beijing
lisi02===13***shenzhen

      3)練習3
        獲取"abg%c*_-dabc*()!gf"字符串中每個字母出現的次數。打印結果爲:a(1)c(2)....

示例代碼:

package com.heisejiuhuche.Collection;

/**
 * 1.將字符串轉換爲字符數組;聲明TreeMap集合
 * 2.遍歷字符數組,將每一個字母(不是字母忽略)在TreeMap中的鍵取值
 * 3.如果該字母沒有值,就將該字母和1存入TreeMap
 * 4.如果有值,就獲取該字母鍵所對應的值,將該值自增1,並和字母一起存入TreeMap
 * 5.聲明StringBuilder容器,將最終結果按格式存入容器,打印
 */

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

public class TreeMapTest1 {
    public static void main(String[] args) {
        String str = "abag%c*_-dadbc*()!gfkk";

        System.out.println(charCount(str));
    }

    public static String charCount(String str) {
        /* 聲明集合 */
        Map<Character, Integer> tm = new TreeMap<Character, Integer>();

        /* 將字符串轉換爲字符數組 */
        char[] ch = str.toCharArray();

        /* 聲明變量用於獲取字母鍵對應的值 */
        int count = 0;

        /* 遍歷字符數組,將每個字母鍵在集合中做匹配 */
        for (int x = 0; x < ch.length; x++) {
            if (!Character.isLetter(ch[x])) {
                continue;
            }

            /* 獲取每個字母鍵對應的值 */
            Integer value = tm.get(ch[x]);

            /* 如果值不爲空,則用count記錄value */
            if (!(value == null)) {
                count = value;
            }
            /*
             * 如果值不爲空,count則爲value的值,自增1; 如果值爲空,count則爲0,自增1
             */
            count++;
            /* 將字母和count存入集合 */
            tm.put(ch[x], count);
            /* count清零,以便下次使用 */
            count = 0;
        }

        /* 聲明StringBuilder容器 */
        StringBuilder sb = new StringBuilder();

        /* 取出最終結果的鍵值對,分別按格式存入StringBuilder */
        for (Iterator<Map.Entry<Character, Integer>> it = tm.entrySet()
                .iterator(); it.hasNext();) {
            Map.Entry<Character, Integer> me = it.next();
            sb.append(me.getKey()).append("(").append(me.getValue())
                    .append(")");
        }

        return sb.toString();
    }
}

程序輸出結果:

a(3)b(2)c(2)d(2)f(1)g(2)k(2)

二、Map擴展知識

    Map集合的集合嵌套。現在有一所學校,學校中有很多教室,每個教室裏面有很多學生,學生有學號和姓名。學校和教室是一個映射關係,教室裏面的學生的學號和姓名是一個映射關係。那麼可以理解成,一個Map存儲着學生的映射,這個學生Map構成教室,嵌套在學校和教室的映射關係Map中。現在要求,在教室中添加學生映射,在學校中添加教室,最後打印每個教室中學生的學好和姓名。

示例代碼:

package com.heisejiuhuche.Collection;

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

public class TreeMapEmbedTest {
    public static void main(String[] args) {
        Map<String, Map<String, String>> school = new HashMap<String, Map<String, String>>();

        Map<String, String> classroom1 = new HashMap<String, String>();

        Map<String, String> classroom2 = new HashMap<String, String>();

        school.put("classroom1", classroom1);
        school.put("classromm2", classroom2);

        classroom1.put("01", "zhangsan");
        classroom1.put("02", "wangwu");
        classroom2.put("03", "zhaoliu");
        classroom2.put("04", "zhouqi");

        printMap(school);
    }

    /* 循環遍歷外層學校集合,取出教室名和教室集合,並打印;
     * 再遍歷教室集合,取出學生學號和姓名,並打印;
     */
    private static void printMap(Map<String, Map<String, String>> hm) {
        for(Iterator<Map.Entry<String, Map<String, String>>> itSch = hm.entrySet().iterator(); itSch.hasNext(); ) {
            Map.Entry<String, Map<String, String>> me1 = itSch.next();
            HashMap<String, String> stu = (HashMap)me1.getValue();
            System.out.println(me1.getKey());
            for(Iterator<Map.Entry<String, String>> itCla = stu.entrySet().iterator(); itCla.hasNext(); ) {
                Map.Entry<String, String> me2 = itCla.next();
                System.out.println(me2.getKey() + "::" + me2.getValue());
            }
        }
    }
}

程序輸出結果:

classromm2
03::zhaoliu
04::zhouqi
classroom1
01::zhangsan
02::wangwu

一般情況下,不會出現這樣的集合嵌套;因爲學生的屬性學號和姓名,會被封裝成學生類。那麼上述情況變爲,學校和教室是一個對應關係,教室和學生類是一個對應關係。學校和教室的關係存儲在Map集合,教室中存儲學生對象而不是映射關係,所以教室變爲一個List集合即可。

示例代碼:

package com.heisejiuhuche.Collection;

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

public class TreeMapEmbedTest2 {
    public static void main(String[] args) {
        Map<String, List<Stu>> school = new HashMap<String, List<Stu>>();

        List<Stu> classroom1 = new ArrayList<Stu>();
        List<Stu> classroom2 = new ArrayList<Stu>();

        school.put("classroom1", classroom1);
        school.put("classroom2", classroom2);

        classroom1.add(new Stu("01", "zhangsan"));
        classroom1.add(new Stu("02", "wangwu"));
        classroom2.add(new Stu("03", "zhaoliu"));
        classroom2.add(new Stu("04", "zhouqi"));

        printMap(school);
    }

    /* 
     * 循環遍歷外層學校集合,取出教室名和教室集合,並打印;
     * 再遍歷教室集合,取出學生學號和姓名,並打印;
     */
    private static void printMap(Map<String, List<Stu>> hm) {
        for(Iterator<Map.Entry<String, List<Stu>>> itSch = hm.entrySet().iterator(); itSch.hasNext(); ) {
            Map.Entry<String, List<Stu>> me1 = itSch.next();
            System.out.println(me1.getKey());
            ArrayList<Stu> stu = (ArrayList)me1.getValue();
            for(Iterator<Stu> itStu = stu.iterator(); itStu.hasNext(); ) {
                System.out.println(itStu.next().toString());
            }
        }
    }
}

/*
 * 聲明學生類
 */
class Stu {
    private String id;
    private String name;

    Stu(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString() {
        return this.id + "::" + this.name;
    }
}

程序輸出結果:

classroom1
01::zhangsan
02::wangwu
classroom2
03::zhaoliu
04::zhouqi
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章