Java集合框架總結(5)——Map接口的使用

Map用於保存具有映射關係的數據(key-vlaue)。Map的key不允許重複,即同一個Map對象的任何兩個key通過equals方法比較總是返回false

Map中包含了一個keySet()方法,用於返回Map所以key組成的Set集合。

    Map集合與Set集合元素的存儲形式很像,如Set接口下有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等實現類和子接口,而Map接口下則有HashMap、LinkedHashMap、SortedMap(接口)、TreeMap、EnumMap等實現類和子接口。

 

    Map的value非常類似List:元素與元素之間可以重複,每個元素可以根據索引(key)來查找。

    Map有時也稱爲字典,或關聯數組。

Map接口中定義如下方法:

  • void clear();刪除Map對象中所有key-value對。
  • boolean containsKey(Object key):查詢Map中是否包含指定key,如果包含則返回true。
  • boolean containsValue(Object value):查詢Map中是否包含一個或多個value,如果包含則返回true。
  • Set entrySet():返回Map中所有包含的key-value對組成的Set集合,每個集合元素都是Map.Entry(Entry是Map的內部類)對象。
  • Object get(Obejct key):返回指定key所對應的value;如果此Map中不包含key,則返回null。
  • boolean isEmpty():查詢該Map是否爲空(即不包含任何key-value對),如果爲空則返回true。
  • Set keySet():返回該Map中所有key所組成的set集合。
  • Object put(Object key, Object value):添加一個key-value對,如果當前Map中已有一個與該key相等的key-value對,則新的key-value對會覆蓋原來的key-value對。
  • Object remove(Object key):刪除指定key對應的key-value對,返回被刪除key所關聯的value,如果該key不存在,返回null。
  • int size():返回該Map裏的key-value對的個數。
  • Collection values():返回該Map裏所有value組成的Collection。

    Map接口提供了大量的實現類,如HashMap和Hashtable等,以及HashMap的子類LinkedHashMap,還有SortedMap子接口及該接口的實現類TreeMap。下面將進行詳細介紹。

    Map中包括一個內部類:Entry。該類封裝了一個key-value對,Entry包含三個方法:

  • Object getkey():返回該Entry裏包含的key值。
  • Object getValue():返回該Entry裏包含的value值。
  • Object setValue():設置該Entry裏包含的value值,並返回新設置的value值。

    可以把Map理解成一個特殊的Set,只是該Set裏包含的集合元素是Entry對象,而不是普通對象。

 

1、HashMap和Hashtable實現類

  HashMap和Hashtable都是Map接口的實現類,Hashtable是一個古老的Map實現類,它從JDK1.0起就有,它包含兩個煩瑣的方法:elements()(類似於Map接口定義的values()方法)和keys()(類似於Map接口定義的keySet()方法),現在很少使用這兩種方法。

兩點區別:

  • Hashtable是一個線程安全的Map實現,但HashMap是線程不安全的實現,所以HashMap比Hashtable的性能高些;但如果多線程訪問同一個Map對象,使用Hashtable實現類更好。
  • Hashtable不允許使用null作爲key和value,如果爲null,則引發NullPointerException異常;但HashMap可以使用null作爲key或value。

  由於HashMap裏的可以不能重複,所以HashMap裏最多隻有一對key-value值爲null,但可以有無數多項key-value對的value爲null。

  HashMap重寫了toString()方法方法總是返回如下格式的字符串:{key1 = value1,key2 = value2..}

  HashMap、Hashtable判斷兩個key相等的標準是:兩個key通過equasl方法比較返回ture,兩個key的hashCode值相等。

LinkedHashMap類

  HashMap有一個子類:LinkedHashMap,它也是雙向鏈表來維護key-value對的次序,該鏈表定義了迭代順序,該迭代順序與key-value對的插入順序保持一致。

LinkedHashMap可以避免對HashMap、Hashtable裏的key-value對進行排序(只要插入key-value對時保持順序即可)。同時又可避免使用TreeMap所增加的成本。

LinkedHashMap需要維護元素的插入順序,因此性能略低於HashMap的性能,但在迭代訪問Map裏的全部元素時將有很好的性能,因爲它以鏈表來維護內部順序。

Properties類

  Properties類是Hashtable類的子類,用於處理屬性文件(例如Windows操作平臺上的ini文件)。Properties類可以把Map對象和屬性文件關聯起來,從而可以把Map對象中的key-value對寫入屬性文件,也可以把屬性文件中的屬性名=屬性值加載到Map對象中。由於屬性文件裏的屬性名、屬性值只能是字符串類型,所以Properties裏的key、value都是字符串類型,該類提供瞭如下三個方法來修改Properties裏的key、value值。

  1. String getProperty(String key):獲取Properties中指定屬性名對應的屬性值,類似於Map的get(Object key)方法。
  2. String getProperty(String key, String defaultValue):該方法與前一個方法基本類似。該方法多一個功能,如果Properties中不存在指定key時,該方法返回默認值。
  3. Object geProperty(String key、String value):設置屬性值,類似Hashtable的put方法。

提供兩個讀、寫屬性文件的方法:

  1. void load(InputStream inStream):從屬性文件(以輸入流表示)中加載屬性名=屬性值,把加載到的屬性名=屬性值對追加到Properties裏(由於Properties是Hashtable)的子類,它不保證key-value對之間的次序)。
  2. void Store(OutputStream out, String comment):將Properties中的key-valu對寫入指定屬性文件(以輸出流表示)。

示例程序:

複製代碼
public class TestProperties
{
    public static void main(String[] args) throws Exception
    {
        Properties props = new Properties();
        //向Properties中增加屬性
        props.setProperty("username" , "yeeku");
        props.setProperty("password" , "123456");
        //將Properties中的屬性保存到a.ini文件中
        props.store(new FileOutputStream("a.ini") , "comment line");
        //新建一個Properties對象
        Properties props2 = new Properties();
        //向Properties中增加屬性
        props2.setProperty("gender" , "male");
        //將a.ini文件中的屬性名-屬性值追加到props2中
        props2.load(new FileInputStream("a.ini") );
        System.out.println(props2);
    }
}
複製代碼

 

 

運行結果:

{password=123456, gender=male, username=yeeku}

 

2、SortedMap接口和TreeMap實現類

  Map接口派生了一個SortedMap子接口,TreeMap爲其實現類。類似TreeSet排序,TreeMap也是基於紅黑樹對TreeMap中所有key進行排序,從而保證TreeMap中所有key-value對處於有序狀態。TreeMap兩種排序方法:

  1. 自然排序:TreeMap的所有key必須實現Comparable接口,而且所有key應該是同一個類的對象,否則將會拋出ClassCastExcepiton異常。
  2. 定製排序:創建TreeMap時,傳入一個Comparator對象,該對象負責對TreeMap中所有key進行排序。採用定製排序時不要求Map的key實現Comparable接口。

  TreeMap中判斷兩個key相等的標準也是兩個key通過equals比較返回true,而通過compareTo方法返回0,TreeMap即認爲這兩個key是相等的。

  如果使用自定義的類作爲TreeMap的key,應重新該類的equals方法和compareTo方法時應有一致的返回結果:即兩個key通過equals方法比較返回true時,它們通過compareTo方法比較應該返回0。如果equals方法與compareTo方法的返回結果不一致,要麼該TreeMap與Map接口的規則有出入(當equals比較返回true,但CompareTo比較不返回0時),要麼TreeMap處理起來性能有所下降(當compareTo比較返回0,當equals比較不返回true時)。

TreeMap中提供了系列根據key順序來訪問Map中key-value對方法:

  1. Map.Entry firstEntry():返回該Map中最小key所對應的key-value對,如果該Map爲空,則返回null。
  2. Object firstKey():返回該Map中的最小key值,如果該Map爲空,則返回null。
  3. Map.Entry lastEntry():返回該Map中最大key所對應的key-value對,如果該Map爲空,或不存在這樣的key-value都返回null。
  4. Object lastKey():返回該Map中的最大key值,如果該Map爲空,或不存在這樣的key都返回null。
  5. Map.Entry higherEntry(Object key):返回該Map中位於key後一位的key-value對(即大於指定key的最小key所對應的key-value對)。如果該Map爲空,則返回null。
  6. Object higherKey():返回該Map中位於key後一位的key值(即大於指定key的最小key值)。如果該Map爲空,或不存在這樣的key都返回null。
  7. Map.Entry lowerEntry(Object key):返回該Map中位於key前一位的key-value對(即小於指定key的最大key所對應的key-value對)。如果該Map爲空,或不存在這樣的key-value則返回null。
  8. Object lowerKey():返回該Map中位於key前一位的key值(即小於指定key的最大key值)。如果該Map爲空,或不存在這樣的key都返回null。
  9. NavigableMap subMap(Object fromKey, boolean fromInclusive, Object tokey, boolean tolnclusive):返回該Map的子Map,其key的範圍從fromKey(是否包括取決於第二個參數)到tokey(是否包括取決於第四個參數)。
  10. SorterMap subMap(Object fromKey, Object toKey):返回該Map的子Map,其key的範圍從fromKey(包括)到toKey(不包括)。
  11. SortedMap tailMap(Object fromKey,boolean inclusive):返回該Map的子Map,其key的範圍是大於fromkey(是否包括取決於第二個參數)的所有key。
  12. NavigableMap headMap(Object toKey, boolean lnclusive):返回該Map的子Map,其key的範圍是小於fromKey(是否包括取決於第二個參數)的所有key。

程序示例:

複製代碼
//R類,重寫了equals方法,如果count屬性相等返回true
//重寫了compareTo(Object obj)方法,如果count屬性相等返回0;
class R implements Comparable
{
    int count;
    public R(int count)
    {
        this.count = count;
    }
    public String toString()
    {
        return "R(count屬性:" + count + ")";
    }
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj != null
            && obj.getClass() == R.class)
        {
            R r = (R)obj;
            if (r.count == this.count)
            {
                return true;
            }
        }
        return false;
    }
    public int compareTo(Object obj)
    {
        R r = (R)obj;
        if (this.count > r.count)
        {
            return 1;
        }
        else if (this.count == r.count)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }
}
public class TestTreeMap
{
    public static void main(String[] args)
    {
        TreeMap tm = new TreeMap();
        tm.put(new R(3) , "輕量級J2EE企業應用實戰");
        tm.put(new R(-5) , "Struts2權威指南");
        tm.put(new R(9) , "ROR敏捷開發最佳實踐");
        System.out.println(tm);
        //返回該TreeMap的第一個Entry對象
        System.out.println(tm.firstEntry());
        //返回該TreeMap的最後一個key值
        System.out.println(tm.lastKey());
        //返回該TreeMap的比new R(2)大的最小key值。
        System.out.println(tm.higherKey(new R(2)));
        //返回該TreeMap的比new R(2)小的最大的key-value對。
        System.out.println(tm.lowerEntry(new R(2)));
        //返回該TreeMap的子TreeMap
        System.out.println(tm.subMap(new R(-1) , new R(4)));

    }
}
複製代碼

 

運行結果:

{R(count屬性:-5)=Struts2權威指南, R(count屬性:3)=輕量級J2EE企業應用實戰, R(count屬性:9)=ROR敏捷開發最佳實踐} 
R(count屬性:-5)=Struts2權威指南 
R(count屬性:9) 
R(count屬性:3) 
R(count屬性:-5)=Struts2權威指南 
{R(count屬性:3)=輕量級J2EE企業應用實戰}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章