成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

Java 集合 Map Properties讀取屬性文件

tomato / 1421人閱讀

摘要:和之間存在單向一對(duì)一關(guān)系,即通過(guò)指定的,總能找到唯一的確定的。從中取出數(shù)據(jù)時(shí),只要給出指定的,就可以取出對(duì)應(yīng)的。有時(shí)也稱(chēng)為字典,或關(guān)聯(lián)數(shù)組。采用定制排序時(shí)不要求的實(shí)現(xiàn)接口中判斷兩個(gè)相等的標(biāo)準(zhǔn)是兩個(gè)通過(guò)方法返回,即認(rèn)為這兩個(gè)是相等的。

map用于保存具有映射關(guān)系的數(shù)據(jù),因此Map集合里保存著兩組值,一組值用于保存Map里的key,另外一組值用于保存Map里的value,key和value都可以是任何引用類(lèi)型的數(shù)據(jù)。Map的key不允許重復(fù),即同一個(gè)Map對(duì)象的任何兩個(gè)key通過(guò)equals方法比較總是返回false。key和value之間存在單向一對(duì)一關(guān)系,即通過(guò)指定的key,總能找到唯一的、確定的value。從Map中取出數(shù)據(jù)時(shí),只要給出指定的key,就可以取出對(duì)應(yīng)的value。

Map有時(shí)也稱(chēng)為字典,或關(guān)聯(lián)數(shù)組。Map接口中定義如下方法:

void clear():刪除Map對(duì)象中所有key-value對(duì)

boolean containsKey(Object key):查詢(xún)Map中是否包含指定key,如果包含則返回true

boolean containsValue(Object value):查詢(xún)Map中是否包含一個(gè)或多個(gè)value,如果包含則返回true

Set entrySet():返回Map中所有包含的key-value對(duì)組成的Set集合,每個(gè)集合元素都是Map.Entry(Entry是Map的內(nèi)部類(lèi))對(duì)象

Object get(Obejct key):返回指定key所對(duì)應(yīng)的value;如果此Map中不包含key,則返回null

boolean isEmpty():查詢(xún)?cè)揗ap是否為空(即不包含任何key-value對(duì)),如果為空則返回true

Set keySet():返回該Map中所有key所組成的set集合

Object put(Object key, Object value):添加一個(gè)key-value對(duì),如果當(dāng)前Map中已有一個(gè)與該key相等的key-value對(duì),則新的key-value對(duì)會(huì)覆蓋原來(lái)的key-value對(duì)

Object remove(Object key):刪除指定key對(duì)應(yīng)的key-value對(duì),返回被刪除key所關(guān)聯(lián)的value,如果該key不存在,返回null

int size():返回該Map里的key-value對(duì)的個(gè)數(shù)

Collection values():返回該Map里所有value組成的Collection

Map中包括一個(gè)內(nèi)部類(lèi):Entry。該類(lèi)封裝了一個(gè)key-value對(duì),Entry包含三個(gè)方法:

Object getkey():返回該Entry里包含的key值

Object getValue():返回該Entry里包含的value值

Object setValue():設(shè)置該Entry里包含的value值,并返回新設(shè)置的value值

    import java.util.*;
    
    public class MapTest
    {
        public static void main(String[] args)
        {
            Map map = new HashMap();
            // 成對(duì)放入多個(gè)key-value對(duì)
            map.put("勒布朗詹姆斯", 6);
            map.put("凱文杜蘭特", 35);
            map.put("斯蒂芬?guī)炖?, 30);
            // 多次放入的key-value對(duì)中value可以重復(fù)
            map.put("維斯布魯克", 0);
            // 放入重復(fù)的key時(shí),新的value會(huì)覆蓋原有的value
            // 如果新的value覆蓋了原有的value,該方法返回被覆蓋的value
            System.out.println(map.put("勒布朗詹姆斯", 23)); // 輸出6
            System.out.println(map); // 輸出的Map集合包含4個(gè)key-value對(duì)
            // 輸出{凱文杜蘭特=35, 勒布朗詹姆斯=23, 斯蒂芬?guī)炖?30, 維斯布魯克=0}
            // 判斷是否包含指定key
            System.out.println("是否包含值為 勒布朗詹姆斯 key:"
                + map.containsKey("勒布朗詹姆斯")); // 輸出true
            // 判斷是否包含指定value
            System.out.println("是否包含值為 0 value:"
                + map.containsValue(0)); // 輸出true
            // 獲取Map集合的所有key組成的集合,通過(guò)遍歷key來(lái)實(shí)現(xiàn)遍歷所有key-value對(duì)
            for (Object key : map.keySet() )
            {
                // map.get(key)方法獲取指定key對(duì)應(yīng)的value
                System.out.println(key + "-->" + map.get(key));
            }
            map.remove("凱文杜蘭特"); // 根據(jù)key來(lái)刪除key-value對(duì)。
            System.out.println(map); // 輸出結(jié)果不再包含 瘋狂凱文杜蘭特=35 的key-value對(duì)
        }
}

Map的實(shí)現(xiàn)類(lèi)都重寫(xiě)了toString()方法,調(diào)用Map對(duì)象的toString()方法總是返回如下格式的字符串:{key1=value, key2=value...}

Java8為Map新增的方法

Java8除了為map增加了remove(Object key, Object value)默認(rèn)方法之外,還增加了如下方法:

Object compute(Object key, BiFunction remappingFunction):該方法使用remappingFunction根據(jù)原key-value對(duì)計(jì)算一個(gè)新value。只要新value不為null,就使用新value覆蓋原value;如果原value不為null,但新value為null,則刪除原key-value對(duì);如果原value、新value同時(shí)為null,那么該方法不改變?nèi)魏蝛ey-value對(duì),直接返回null

Object computeIfAbsent(Object key, Function mappingFunction):如果傳給該方法的key參數(shù)在Map中對(duì)應(yīng)的value為null,則使用mappingFunction根據(jù)key計(jì)算一個(gè)新的結(jié)果,如果計(jì)算結(jié)果不為null,則用計(jì)算結(jié)果覆蓋原有value。如果原Map原來(lái)不包含該key,那么該方法可能會(huì)添加一組key-value對(duì)

Object computeIfPresent(Object key ,BiFunction remappingFunction):如果傳給該方法的key參數(shù)在Map中對(duì)應(yīng)的value不為null,該方法將使用remappingFunction根據(jù)原key、value計(jì)算一個(gè)新的結(jié)果,如果計(jì)算結(jié)果不為null,則使用該結(jié)果覆蓋原來(lái)的value,如果計(jì)算的結(jié)果為null,則刪除原key-value對(duì)

void forEach(BiConsumer action):該方法是Java 8為Map新增的一個(gè)遍歷key-value對(duì)的方法

Object getOrDefault(Object key, V defaultValue):獲取指定key對(duì)應(yīng)的value。如果該key不存在則返回defaultValue

Object merge(Object key, Object value, BiFunction remappingFunction):該方法會(huì)先根據(jù)Key參數(shù)獲取該Map中對(duì)應(yīng)的value。如果獲得value為null,則直接用傳入的value覆蓋原有的value(在這中情況下,可能要添加一組key-value對(duì));如果獲取的value不為null,則使用remappingFunction 函數(shù)根據(jù)原value、新value計(jì)算一新的結(jié)果,并用得到的結(jié)果去覆蓋原有的value

Object putIfAbsent(Object key, Object value):該方法會(huì)自動(dòng)檢測(cè)指定key對(duì)應(yīng)的value是否為null,如果該key對(duì)應(yīng)的value為null,該方法將會(huì)用新value代替原來(lái)的null值

Object replace(Object key, Object value):將Map中指定key對(duì)應(yīng)的value替換成新的value。與傳統(tǒng)的put方法不同的是,該方法不可能添加新的key-value對(duì)。如果嘗試替換的key在原Map中不存在,該方法不會(huì)添加key-value對(duì),而是返回null

boolean replace(K key, V oldValue, V newValue)
將Map中指定key-value對(duì)的原value提換成新value。如果在Map中找到指定的key-value對(duì),則執(zhí)行替換并返回true,否額返回false

replaceAll(Bifunction function):該方法使用Bifunction 對(duì)原key-value對(duì)執(zhí)行計(jì)算,并將計(jì)算結(jié)果作為key-value對(duì)的value的值

import java.util.*;

public class MapTest2
{
    public static void main(String[] args)
    {
        Map map = new HashMap();
        // 成對(duì)放入多個(gè)key-value對(duì)
        map.put("勒布朗詹姆斯", 6);
        map.put("凱文杜蘭特", 35);
        map.put("斯蒂芬?guī)炖?, 30);
        // 嘗試替換key為"維斯布魯克"的value,由于原Map中沒(méi)有對(duì)應(yīng)的key,
        // 因此對(duì)Map沒(méi)有改變,不會(huì)添加新的key-value對(duì)
        map.replace("維斯布魯克", 0);
        System.out.println(map);
        // 使用原value與參數(shù)計(jì)算出來(lái)的結(jié)果覆蓋原有的value
        map.merge("勒布朗詹姆斯", 17 ,
            (oldVal , param) -> (Integer)oldVal + (Integer)param);
        System.out.println(map); // "勒布朗詹姆斯"的value增大了17,變?yōu)?3
        // 當(dāng)key為"詹姆斯哈登"對(duì)應(yīng)的value為null(或不存在時(shí)),使用計(jì)算的結(jié)果作為新value
        map.computeIfAbsent("凱文加內(nèi)特" , (key)->((String)key).length());
        System.out.println(map); // map中添加了 凱文加內(nèi)特=5 這組key-value對(duì)
        // 當(dāng)key為"凱文加內(nèi)特"對(duì)應(yīng)的value存在時(shí),使用計(jì)算的結(jié)果作為新value
        map.computeIfPresent("凱文加內(nèi)特",
            (key , value) -> (Integer)value + 16);
        System.out.println(map); // map中 凱文加內(nèi)特=5 變成 凱文加內(nèi)特=21
    }
}

Java8改進(jìn)的HashMap和Hashtable實(shí)現(xiàn)類(lèi)

HashMap和Hashtable都是Map接口的典型實(shí)現(xiàn)類(lèi),它們之間的關(guān)系完全類(lèi)似于ArrayList和Vector的關(guān)系

使用HashMap存在key沖突時(shí)依然具有較好的性能

Hashtable是一個(gè)線(xiàn)程安全的Map實(shí)現(xiàn),但HashMap是線(xiàn)程不安全的實(shí)現(xiàn),所以HashMap比Hashtable的性能高一點(diǎn);但如果有多線(xiàn)程訪(fǎng)問(wèn)同一個(gè)Map對(duì)象時(shí),使用Hashtable實(shí)現(xiàn)類(lèi)會(huì)更好

Hashtable不允許使用null作為key和value,如果試圖把null值放進(jìn)Hashtable中,將會(huì)引發(fā)NullPointerException異常;但HashMap可以使用null作為key或value

由于HashMap里的key不能重復(fù),所以HashMap里最多只有一個(gè)key-value對(duì)的key為null,但可以有無(wú)數(shù)多個(gè)key-value對(duì)的value為null

public class NullInHashMap
{
    public static void main(String[] args)
    {
        HashMap hm = new HashMap();
        // 試圖將兩個(gè)key為null的key-value對(duì)放入HashMap中
        hm.put(null, null);
        hm.put(null, null);    // ①
        // 將一個(gè)value為null的key-value對(duì)放入HashMap中
        hm.put("a", null);    // ②
        // 輸出Map對(duì)象
        System.out.println(hm);
    }
}

①代碼處無(wú)法將key-value對(duì)放入,因?yàn)镸ap中已經(jīng)有一個(gè)key-value對(duì)的key為null,所以無(wú)法再放入key為null值的key-value對(duì)

{null=null, a=null}

為了成功的在HashMap、Hashtable中存儲(chǔ)、獲取對(duì)象,用作key的對(duì)象必須實(shí)現(xiàn)hashCode()方法和equals()方法

與HashSet集合不能保證元素的順序一樣,HashMap、Hashtable也不能保證其中key-value對(duì)的順序。類(lèi)似于HashSet的是,HashMap、Hashtable判斷兩個(gè)key相等的標(biāo)準(zhǔn)也是:兩個(gè)key通過(guò)equals方法比較返回true,兩個(gè)key的hashCode值也相等。除此之外,HashMap、Hashtable中還包含一個(gè)containsValue()方法用于判斷是否包含指定value。HashMap、Hashtable判斷兩個(gè)value相等的標(biāo)準(zhǔn)更簡(jiǎn)單:只要兩個(gè)對(duì)象通過(guò)equals比較返回true即可

import java.util.Hashtable;

class A
{
    int count;
    public A(int count) 
    {
        this.count = count;
    }
    // 根據(jù)count的值來(lái)判斷兩個(gè)對(duì)象是否相等
    public boolean equals(Object obj) 
    {
        if (obj == this) 
        {
            return true;
        }
        if (obj != null && obj.getClass() == A.class) 
        {
            A a = (A)obj;
            return this.count == a.count; 
        }
        return false;
    }
    // 根據(jù)count來(lái)計(jì)算hashCode值
    public int hashCode() 
    {
        return this.count;
    }
}

class B
{
    // 重寫(xiě)equals()方法,B對(duì)象與任何對(duì)象通過(guò)equals()方法比較都返回ture
    public boolean equals() 
    {
        return true;
    }
}

public class HashtableTest2 
{
    public static void main(String[] args) 
    {
        Hashtable ht = new Hashtable<>();
        ht.put(new A(23), "勒布朗詹姆斯");
        ht.put(new A(0), "凱文樂(lè)福");
        // ht.put(new A(2), "凱里歐文");
        ht.put(new A(6), new B());
        System.out.println(ht);
        // 只要兩個(gè)對(duì)象通過(guò)equals()方法比較返回true
        // Hashtable就認(rèn)為它們是相等的value
        // 由于Hashtable中有一個(gè)B對(duì)象
        // 它與任何對(duì)象通過(guò)equals比較都相等,所以下面輸出true
        System.out.println(ht.containsValue("克利夫蘭騎士")); // ① 輸出true
        // 只要兩個(gè)A對(duì)象的count相等,它們通過(guò)equals比較返回true,且hashCode相等
        // Hashtable即認(rèn)為它們是相同的key,所以下面輸出true
        System.out.println(ht.containsKey(new A(23)));   // ② 輸出true
        // 下面語(yǔ)句可以刪除最后一個(gè)key-value對(duì)
        ht.remove(new A(6));    //③
        System.out.println(ht);
    }
}

與HashSet類(lèi)似的是,如果使用可變對(duì)象作為HashMap、Hashtable的key,并且程序修改了作為key的可變對(duì)象,可能引發(fā)與HashSet類(lèi)似的情形:程序無(wú)法準(zhǔn)確訪(fǎng)問(wèn)到Map中被修改過(guò)key。 所以說(shuō)盡量不要使用可變對(duì)象作為HashMapHashtable的key

LinkedHashMap實(shí)現(xiàn)類(lèi)

HashSet有一個(gè)子類(lèi)是LinkedHashSet,HashMap也有一個(gè)LinkedHashMap子類(lèi);LinkedHashMap也使用雙向鏈表來(lái)維護(hù)key-value對(duì)的次序;該鏈表負(fù)責(zé)維護(hù)key的迭代順序,迭代順序與key-value的插入順序一致

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

LinkedHashMap需要維護(hù)元素的插入順序,因此性能略低于HashMap的性能,但在迭代訪(fǎng)問(wèn)Map里的全部元素時(shí)將有很好的性能,因?yàn)樗枣湵韥?lái)維護(hù)內(nèi)部順序

public class LinkedHashMapTest
{
    public static void main(String[] args)
    {
        LinkedHashMap scores = new LinkedHashMap();
        scores.put("勒布朗詹姆斯", 23);
        scores.put("維斯布魯克", 0);
        scores.put("斯蒂芬?guī)炖?, 30);
        // 調(diào)用forEach方法遍歷scores里的所有key-value對(duì)
        scores.forEach((key, value) -> System.out.println(key + "-->" + value));
    }
}

使用Properties讀取屬性文件

Properties類(lèi)是Hashtable類(lèi)的子類(lèi),用于處理屬性文件(例如Windows操作平臺(tái)上的ini文件)。Properties類(lèi)可以把Map對(duì)象和屬性文件關(guān)聯(lián)起來(lái),從而可以把Map對(duì)象中的key-value對(duì)寫(xiě)入屬性文件,也可以把屬性文件中的“屬性名=屬性值”加載到Map對(duì)象中。由于屬性文件里的屬性名、屬性值只能是字符串類(lèi)型,所以Properties里的key、value都是字符串類(lèi)型

修改Properties里的key、value值的方法

String getProperty(String key):獲取Properties中指定屬性名對(duì)應(yīng)的屬性值,類(lèi)似于Map的get(Object key)方法

String getProperty(String key, String defaultValue):該方法與前一個(gè)方法基本類(lèi)似。該方法多一個(gè)功能,如果Properties中不存在指定key時(shí),該方法返回默認(rèn)值

Object geProperty(String key、String value):設(shè)置屬性值,類(lèi)似Hashtable的put方法

讀、寫(xiě)屬性文件的方法:

void load(InputStream inStream):從屬性文件(以輸入流表示)中加載屬性名=屬性值,把加載到的屬性名=屬性值對(duì)追加到Properties里(由于Properties是Hashtable)的子類(lèi),它不保證key-value對(duì)之間的次序)

void Store(OutputStream out, String comment):將Properties中的key-valu對(duì)寫(xiě)入指定屬性文件(以輸出流表示)

public class PropertiesTest
{
    public static void main(String[] args)
        throws Exception
    {
        Properties props = new Properties();
        // 向Properties中增加屬性
        props.setProperty("username" , "LeBron");
        props.setProperty("teams" , "Cavaliers");
        // 將Properties中的key-value對(duì)保存到a.ini文件中
        props.store(new FileOutputStream("NBA.ini")
            , "comment line");   //①
        // 新建一個(gè)Properties對(duì)象
        Properties props2 = new Properties();
        // 向Properties中增加屬性
        props2.setProperty("gender" , "male");
        // 將a.ini文件中的key-value對(duì)追加到props2中
        props2.load(new FileInputStream("NBA.ini") );   //②
        System.out.println(props2);
    }
}

SortedMap接口和TreeMap實(shí)現(xiàn)類(lèi)

Map接口派生了一個(gè)SortedMap子接口,TreeMap為其實(shí)現(xiàn)類(lèi)。類(lèi)似TreeSet排序,TreeMap也是基于紅黑樹(shù)對(duì)TreeMap中所有key進(jìn)行排序,從而保證TreeMap中所有key-value對(duì)處于有序狀態(tài)。TreeMap兩種排序方法:

自然排序:TreeMap的所有key必須實(shí)現(xiàn)Comparable接口,而且所有key應(yīng)該是同一個(gè)類(lèi)的對(duì)象,否則將會(huì)拋出ClassCastExcepiton異常

定制排序:創(chuàng)建TreeMap時(shí),傳入一個(gè)Comparator對(duì)象,該對(duì)象負(fù)責(zé)對(duì)TreeMap中所有key進(jìn)行排序。采用定制排序時(shí)不要求Map的key實(shí)現(xiàn)Comparable接口

TreeMap中判斷兩個(gè)key相等的標(biāo)準(zhǔn)是:兩個(gè)key通過(guò)compareTo方法返回0,TreeMap即認(rèn)為這兩個(gè)key是相等的。

如果使用自定義的類(lèi)作為T(mén)reeMap的key,應(yīng)重新該類(lèi)的equals方法和compareTo方法時(shí)應(yīng)有一致的返回結(jié)果:即兩個(gè)key通過(guò)equals方法比較返回true時(shí),它們通過(guò)compareTo方法比較應(yīng)該返回0。如果equals方法與compareTo方法的返回結(jié)果不一致,要么該TreeMap與Map接口的規(guī)則有出入(當(dāng)equals比較返回true,但CompareTo比較不返回0時(shí)),要么TreeMap處理起來(lái)性能有所下降(當(dāng)compareTo比較返回0,當(dāng)equals比較不返回true時(shí))

根據(jù)key順序來(lái)訪(fǎng)問(wèn)Map中key-value對(duì)方法:

Map.Entry firstEntry():返回該Map中最小key所對(duì)應(yīng)的key-value對(duì),如果該Map為空,則返回null

Map.Entry lastEntry():返回該Map中最大key所對(duì)應(yīng)的key-value對(duì),如果該Map為空,或不存在這樣的key-value都返回null

Object firstKey():返回該Map中的最小key值,如果該Map為空,則返回null

Object lastKey():返回該Map中的最大key值,如果該Map為空,或不存在這樣的key都返回null

Map.Entry higherEntry(Object key):返回該Map中位于key后一位的key-value對(duì)(即大于指定key的最小key所對(duì)應(yīng)的key-value對(duì))。如果該Map為空,則返回null

Map.Entry lowerEntry(Object key):返回該Map中位于key前一位的key-value對(duì)(即小于指定key的最大key所對(duì)應(yīng)的key-value對(duì))。如果該Map為空,或不存在這樣的key-value則返回null

Object higherKey():返回該Map中位于key后一位的key值(即大于指定key的最小key值)。如果該Map為空,或不存在這樣的key都返回null

Object lowerKey():返回該Map中位于key前一位的key值(即小于指定key的最大key值)。如果該Map為空,或不存在這樣的key都返回null

NavigableMap subMap(Object fromKey, boolean fromInclusive, Object
tokey, boolean tolnclusive):返回該Map的子Map,其key的范圍從fromKey(是否包括取決于第二個(gè)參數(shù))到tokey(是否包括取決于第四個(gè)參數(shù))。

NavigableMap headMap(Object toKey, boolean lnclusive):返回該Map的子Map,其key的范圍是小于toKey(是否包括取決于第二個(gè)參數(shù))的所有key

NavigableMap tailMap(Object fromKey, boolean lnclusive):返回該Map的子Map,其key的范圍是大于fromKey(是否包括取決于第二個(gè)參數(shù))的所有key

SorterMap subMap(Object fromKey, Object toKey):返回該Map的子Map,其key的范圍從fromKey(包括)到toKey(不包括)

SortedMap headMap(Object toKey):返回該Map的子Map,其key的范圍是小于tokey(是否包括取決于第二個(gè)參數(shù))的所有key

SortedMap tailMap(Object fromKey):返回該Map的子Map,其key的范圍是大于fromkey(是否包括取決于第二個(gè)參數(shù))的所有key

class R implements Comparable
{
    int count;
    public R(int count)
    {
        this.count = count;
    }
    public String toString()
    {
        return "R[count:" + count + "]";
    }
    // 根據(jù)count來(lái)判斷兩個(gè)對(duì)象是否相等。
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj != null    && obj.getClass() == R.class)
        {
            R r = (R)obj;
            return r.count == this.count;
        }
        return false;
    }
    // 根據(jù)count屬性值來(lái)判斷兩個(gè)對(duì)象的大小。
    public int compareTo(Object obj)
    {
        R r = (R)obj;
        return count > r.count ? 1 :
            count < r.count ? -1 : 0;
    }
}
public class TreeMapTest
{
    public static void main(String[] args)
    {
        TreeMap tm = new TreeMap();
        tm.put(new R(3) , "輕量級(jí)Java EE企業(yè)應(yīng)用實(shí)戰(zhàn)");
        tm.put(new R(-5) , "瘋狂Java講義");
        tm.put(new R(9) , "瘋狂Android講義");
        System.out.println(tm);
        // 返回該TreeMap的第一個(gè)Entry對(duì)象
        System.out.println(tm.firstEntry());
        // 返回該TreeMap的最后一個(gè)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對(duì)。
        System.out.println(tm.lowerEntry(new R(2)));
        // 返回該TreeMap的子TreeMap
        System.out.println(tm.subMap(new R(-1) , new R(4)));
    }
}
WeakHashMap

HashMap中的key保存的是實(shí)際對(duì)象的強(qiáng)引用,這意味著只要該HashMap對(duì)象不被銷(xiāo)毀,該HashMap的所有key所引用的對(duì)象就不會(huì)被垃圾回收,HashMap也不會(huì)自動(dòng)刪除這些key所對(duì)應(yīng)的key-value對(duì)

WeakHashMap中的key保存的是實(shí)際對(duì)象的弱引用,這意味著只要該WeakHashMap對(duì)象沒(méi)被其他強(qiáng)對(duì)象引用變量引用,則這些key所引用的對(duì)象可能被垃圾回收,就有可能會(huì)被垃圾回收機(jī)制回收對(duì)應(yīng)的Key-value,WeakHashMap也可能自動(dòng)刪除這些key所對(duì)應(yīng)的key-value對(duì)

public class WeakHashMapTest
{
    public static void main(String[] args)
    {
        WeakHashMap whm = new WeakHashMap();
        // 將WeakHashMap中添加三個(gè)key-value對(duì),
        // 三個(gè)key都是匿名字符串對(duì)象(沒(méi)有其他引用)
        whm.put(new String("南特") , new String("Nantes"));
        whm.put(new String("巴黎") , new String("Paris"));
        whm.put(new String("波爾多") , new String("Bordeaux"));
        //將 WeakHashMap中添加一個(gè)key-value對(duì),
        // 該key是一個(gè)系統(tǒng)緩存的字符串對(duì)象。
        whm.put("馬賽" , new String("Marseille"));    // ①
        // 輸出whm對(duì)象,將看到4個(gè)key-value對(duì)。
        System.out.println(whm);
        // 通知系統(tǒng)立即進(jìn)行垃圾回收
        System.gc();
        System.runFinalization();
        // 通常情況下,將只看到一個(gè)key-value對(duì)。
        System.out.println(whm);
    }
}

當(dāng)系統(tǒng)進(jìn)行垃圾回收時(shí),刪除了WeakHashMap對(duì)象的前三個(gè)key-value對(duì)。因?yàn)樘砑忧叭齻€(gè)key-value對(duì)時(shí),這三個(gè)key都是匿名的字符串對(duì)象,WeakHashMap只保留了對(duì)它們的弱引用,這樣垃圾回收時(shí)會(huì)自動(dòng)刪除這三個(gè)key-value對(duì)。第4個(gè)key-value對(duì)的key是一個(gè)字符串直接量(系統(tǒng)會(huì)自動(dòng)保留對(duì)該字符串對(duì)象的強(qiáng)引用),所以垃圾回收時(shí)不會(huì)回收它

IdentityHashMap實(shí)現(xiàn)類(lèi)

IdentityHashMap的實(shí)現(xiàn)機(jī)制與HashMap基本相似,在IdentityHashMap中,判斷兩個(gè)key是否相等,是通過(guò)嚴(yán)格相等即(key1==key2)來(lái)判斷的,而HashMap是通過(guò)equals()方法和hashCode()這兩個(gè)方法來(lái)判斷key是否相等的。IdentityHashMap允許使用null作為key和value,不保證key-value對(duì)之間的順序,不保證它們的順序隨時(shí)間的推移保持不變

public class IdentityHashMapTest
{
    public static void main(String[] args)
    {
        IdentityHashMap ihm = new IdentityHashMap();
        // 下面兩行代碼將會(huì)向IdentityHashMap對(duì)象中添加兩個(gè)key-value對(duì)
        ihm.put(new String("勒布朗詹姆斯") , 23);
        ihm.put(new String("勒布朗詹姆斯") , 6);
        // 下面兩行代碼只會(huì)向IdentityHashMap對(duì)象中添加一個(gè)key-value對(duì)
        ihm.put("科比布萊恩特" , 8);
        ihm.put("科比布萊恩特" , 24);
        System.out.println(ihm);
    }
}

前2個(gè)key-value對(duì)中的key是新創(chuàng)建的字符串對(duì)象,它們通過(guò)==比較不相等,所以IdentityHashMap會(huì)把它們當(dāng)成2個(gè)key來(lái)處理;后2個(gè)key-value對(duì)中的key都是字符串直接量,而且它們的字符序列完全相同,Java使用常量池來(lái)管理字符串直接量,所以它們通過(guò)==比較返回true,IdentityHashMap會(huì)認(rèn)為它們是同一個(gè)Key,因此只有一次可以添加成功

EnumMap實(shí)現(xiàn)類(lèi)

EnumMap是一個(gè)與枚舉類(lèi)一起使用的Map實(shí)現(xiàn),EnumMap中的所有key都必須是單個(gè)枚舉類(lèi)的枚舉值。創(chuàng)建EnumMap時(shí)必須顯式或隱式指定它對(duì)應(yīng)的枚舉類(lèi)。EnumMap具有如下特征:

EnumMap在內(nèi)部以數(shù)組形式保存,所以這種實(shí)現(xiàn)形式非常緊湊、高效

EunmMap根據(jù)key的自然順序(即枚舉值在枚舉類(lèi)中的定義順序)來(lái)維護(hù)key-value對(duì)的順序。當(dāng)程序通過(guò)keySet()、entrySet()、values()等方法遍歷EnumMap時(shí)可以看到這種順序

EnumMap不允許使用null作為key,但允許使用null作為value。如果試圖使用null作為key時(shí)將拋出NullpointerException。如果只是查詢(xún)是否包含值為null的key,或只是刪除值為null的key,都不會(huì)拋出異常

enum NBA_Player
{
    James,Westbrook,Curry,Harden
}
public class EnumMapTest
{
    public static void main(String[] args)
    {
        // 創(chuàng)建EnumMap對(duì)象,該EnumMap的所有key都是Season枚舉類(lèi)的枚舉值
        EnumMap enumMap = new EnumMap(NBA_Player.class);
        enumMap.put(NBA_Player.Westbrook, "俄克拉荷馬雷霆");
        enumMap.put(NBA_Player.James, "克利夫蘭騎士");
        System.out.println(enumMap);
    }
}

創(chuàng)建EnumMap對(duì)象時(shí)指定它的key只能是NBA_Player枚舉類(lèi)的枚舉值。如果向該EnumMap中添加兩個(gè)key-value對(duì)后,這兩個(gè)key-value對(duì)將會(huì)以NBA_Player枚舉值的自然順序排序

各Map實(shí)現(xiàn)類(lèi)的性能分析

HashMap和Hashtable的實(shí)現(xiàn)機(jī)制幾乎一樣,但由于Hashtable是一個(gè)古老的、線(xiàn)程安全的集合,因此HashMap通常比Hashtable要快

TreeMap比HashMap和Hashtable要慢(尤其在插入、刪除key-value對(duì)時(shí)更慢),因?yàn)門(mén)reeMap底層采用紅黑樹(shù)來(lái)管理key-value對(duì)(紅黑樹(shù)的每個(gè)節(jié)點(diǎn)就是一個(gè)key-value對(duì))
TreeMap中的key-value總是處于有序狀態(tài),無(wú)需專(zhuān)門(mén)進(jìn)行排序操作。當(dāng)TreeMap被填充后,就可以調(diào)用keySet(),取得由key組成的Set,然后使用toArray()方法生成key的數(shù)組,接下來(lái)使用Arrays的binarySearch()方法在已排序的數(shù)組中快速查詢(xún)對(duì)象

LinkedHashMap比HashMap慢一點(diǎn),因?yàn)樗枰S護(hù)鏈表來(lái)保持Map中key-value時(shí)的添加順序

IdentityHashMap性能沒(méi)有特別出色支持,采用與HashMap基本相似的實(shí)現(xiàn),只是它使用==而不是equals()方法來(lái)判斷元素相等

EnumMap性能最好,但它只能使用同一個(gè)枚舉類(lèi)的枚舉值作為key

對(duì)于一般的應(yīng)用場(chǎng)景,程序應(yīng)該多考慮使用HashMap,因?yàn)镠ashMap正是為快速查詢(xún)?cè)O(shè)計(jì)的(HashMap底層其實(shí)也是采用數(shù)組來(lái)存儲(chǔ)key-value對(duì))。但如果程序需要一個(gè)總是排好序的Map時(shí),則可以考慮使用TreeMap

HashSet和HashMap的性能選項(xiàng)

對(duì)于HashSet及其子類(lèi)而言,它們采用hash算法來(lái)決定集合中元素的存儲(chǔ)位置,并通過(guò)hash算法來(lái)控制集合的大小;
對(duì)于HashMap、Hashtable及其子類(lèi)而言,它們采用hash算法來(lái)覺(jué)得Map中key的存儲(chǔ),并通過(guò)hash算法來(lái)增加key集合的大小

hash表里可以存儲(chǔ)元素的位置被稱(chēng)為“桶(bucket)”,在通常情況下,單個(gè)“桶”里存儲(chǔ)一個(gè)元素時(shí),此時(shí)擁有最好的性能:hash算法可以根據(jù)hashCode值計(jì)算出“桶”的存儲(chǔ)位置,接著從“桶”中取出元素。但hash表的狀態(tài)是open的:在發(fā)生“hash沖突”的情況下,單個(gè)桶會(huì)存儲(chǔ)多個(gè)元素,這些元素以鏈表形式存儲(chǔ),必須按順序搜索。如下圖所示是hash表保存各元素

因?yàn)镠ashSet和HashMap、Hashtable都使用hash算法來(lái)決定其元素(HashMap則只考慮key)的存儲(chǔ),因此HashSet、HashMap的hash表中包含如下屬性

容量(capacity):hash表中桶的數(shù)量

初始化容量(inital capacity):創(chuàng)建hash表時(shí)桶的數(shù)量。HashMap和HashSet都允許在構(gòu)造器中指定初始化容量

尺寸(size):當(dāng)前hash表中記錄的數(shù)量

負(fù)載因子(load factor):負(fù)載因子等于“size/capacity”。負(fù)載因子為0,表示空的hash表,0.5表示半滿(mǎn)的hash表,依次類(lèi)推。輕負(fù)載的hash表具有沖突少,適宜插入與查詢(xún)的特點(diǎn)(但是用Iterator迭代元素時(shí)比較慢)

除此之外,hash表里還有一個(gè)“負(fù)載極限”是一個(gè)0~1的數(shù)值,“負(fù)載極限”決定了hash表的最大填滿(mǎn)程序。
當(dāng)hash表中的負(fù)載因子達(dá)到指定的“負(fù)載極限”時(shí),hash表會(huì)自動(dòng)成倍地增加容量(桶的數(shù)量),并將原有的對(duì)象重新分配,嵌入新的桶內(nèi),這稱(chēng)為rehashing

HashSet和HashMap、Hashtable的構(gòu)造器允許指定一個(gè)負(fù)載極限,HashSet和HashMap、Hashtable默認(rèn)的“負(fù)載極限”為0.75,這表明當(dāng)該hash表的3/4已經(jīng)被填滿(mǎn)時(shí),hash表會(huì)發(fā)生rehashing

“負(fù)載極限”的默認(rèn)值(0.75)是時(shí)間和空間成本上的一種折中:較高的“負(fù)載極限”可以降低hash表所占用的內(nèi)存空間,但會(huì)增加查詢(xún)數(shù)據(jù)和時(shí)間的開(kāi)銷(xiāo),而查詢(xún)是最頻繁的操作(HashMap的get()和put()方法都要用到查詢(xún));
較低的“負(fù)載極限”會(huì)提高查詢(xún)數(shù)據(jù)的性能,但會(huì)增加hash表所占用的內(nèi)存開(kāi)銷(xiāo)。

如果開(kāi)始就知道HashSet和HashMap、Hashtable會(huì)保存很多記錄,則可以在創(chuàng)建時(shí)就使用較大的初始化容量,如果初始化容量始終大于HashSet、Hashtable和HashMap所包含的最大記錄數(shù)除以“負(fù)載極限”,就不會(huì)發(fā)生rehashing。使用足夠大的初始化容量創(chuàng)建HashSet和HashMap、Hashtable時(shí),可以更高效地增加記錄,但將初始化容量設(shè)置太高會(huì)浪費(fèi)空間,所以不要講初始化容量設(shè)置過(guò)高

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/66404.html

相關(guān)文章

  • Properties之使用Properties集合存儲(chǔ)數(shù)據(jù),遍歷,store,load方法

    摘要:通過(guò)找到值此方法相當(dāng)于集合中的方法返回此屬性列表中的鍵集,其中該鍵及其對(duì)應(yīng)值是字符串此方法相當(dāng)于集合中的方法創(chuàng)建集合對(duì)象使用往集合中添加數(shù)據(jù)趙麗穎迪麗熱巴古力娜扎使用把集合中的鍵取出存儲(chǔ)到一個(gè)集合中遍歷集合取出集合的每一個(gè)鍵使用方法通過(guò)獲取 package com.itheima.demo07.Prop; import java.io.FileOutputStream;import j...

    paraller 評(píng)論0 收藏0
  • 1、Properties集合 2、序列化流與反序列化流 3、打印流 4、commons-IO

    摘要:集合的特點(diǎn)集合的特點(diǎn)類(lèi)介紹類(lèi)表示了一個(gè)持久的屬性集??杀4嬖诹髦谢驈牧髦屑虞d。屬性列表中每個(gè)鍵及其對(duì)應(yīng)值都是一個(gè)字符串特點(diǎn)的子類(lèi),集合中的方法都可以用。該集合沒(méi)有泛型。鍵值可以存儲(chǔ)到集合中,也可以存儲(chǔ)到持久化的設(shè)備硬盤(pán)盤(pán)光盤(pán)上。 01Properties集合的特點(diǎn) * A: Properties集合的特點(diǎn) * a: Properties類(lèi)介紹 * Propert...

    aboutU 評(píng)論0 收藏0
  • Java編程基礎(chǔ)23——IO(其他流)&Properties

    摘要:但它融合了和的功能。支持對(duì)隨機(jī)訪(fǎng)問(wèn)文件的讀取和寫(xiě)入。的概述和作為集合的使用了解的概述類(lèi)表示了一個(gè)持久的屬性集??杀4嬖诹髦谢驈牧髦屑虞d。屬性列表中每個(gè)鍵及其對(duì)應(yīng)值都是一個(gè)字符串。 1_序列流(了解) 1.什么是序列流 序列流可以把多個(gè)字節(jié)輸入流整合成一個(gè), 從序列流中讀取數(shù)據(jù)時(shí), 將從被整合的第一個(gè)流開(kāi)始讀, 讀完一個(gè)之后繼續(xù)讀第二個(gè), 以此類(lèi)推. 2.使用方式 整合兩個(gè): S...

    vvpale 評(píng)論0 收藏0
  • Hibernate配置及自定義注冊(cè)映射文件

    摘要:一配置屬性詳解可以在各式各樣不同環(huán)境下工作而設(shè)計(jì)的因此存在著大量的配置參數(shù)。以簡(jiǎn)便操作,多數(shù)配置參數(shù)都有默認(rèn)的配置值也是我們?nèi)粘J褂玫谋仨毱贰? Hibernate (開(kāi)放源代碼的對(duì)象關(guān)系映射框架) Hibernate是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝, 它將POJO與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的orm框架,hibernat...

    coordinate35 評(píng)論0 收藏0
  • Spring筆記01_下載_概述_監(jiān)聽(tīng)器

    摘要:簡(jiǎn)單來(lái)說(shuō),是一個(gè)輕量級(jí)的控制反轉(zhuǎn)和面向切面的容器框架。變成的支持提供面向切面編程,可以方便的實(shí)現(xiàn)對(duì)程序進(jìn)行權(quán)限攔截,運(yùn)行監(jiān)控等功能。用于反射創(chuàng)建對(duì)象,默認(rèn)情況下調(diào)用無(wú)參構(gòu)造函數(shù)。指定對(duì)象的作用范圍。 1.Spring介紹 1.1 Spring概述 Spring是一個(gè)開(kāi)源框架,Spring是于2003 年興起的一個(gè)輕量級(jí)的Java 開(kāi)發(fā)框架,由Rod Johnson 在其著作Expert...

    reclay 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<