一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java中的hashmap

 小王曾是少年 2022-08-24 發(fā)布于江蘇

一、數(shù)據(jù)結(jié)構(gòu)之哈希表

所謂哈希表,是一種數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu),我們可以通過數(shù)據(jù)的“關(guān)鍵碼值”來直接訪問表。通過散列的方法(可以理解為一種特殊的數(shù)學(xué)過程=_=),我們可以把關(guān)鍵碼值映射到數(shù)組中的不同位置。

設(shè)計(jì)散列系統(tǒng)的目標(biāo)是對于任一個(gè)關(guān)鍵碼值Key,都能通過某散列函數(shù)的計(jì)算來得到一個(gè)數(shù)組中的存儲(chǔ)下標(biāo),使得該位置存儲(chǔ)值Value。這樣一來就很可能出現(xiàn)不同的關(guān)鍵碼值對應(yīng)同一個(gè)數(shù)組下標(biāo)的情況,因此設(shè)計(jì)沖突解決策略也是必須的。
一種很容易想到的解決沖突的策略是,每當(dāng)要存儲(chǔ)一個(gè)關(guān)鍵值為Key的數(shù)據(jù)時(shí),首先判斷計(jì)算出的存儲(chǔ)下標(biāo)處是否已經(jīng)存儲(chǔ)了一個(gè)數(shù)據(jù),如果是則將下標(biāo)值進(jìn)行“+1”操作,繼續(xù)判斷,直到判斷為否時(shí)存入數(shù)據(jù)。

根據(jù)以上原理我們可以設(shè)計(jì)一個(gè)簡單的程序來模擬哈希表的實(shí)現(xiàn)(這里假設(shè)Key和Value的數(shù)據(jù)類型都是int)
public class HashDemo {

    static int size = 1000;
    static int[] hash = new int[size];
    int currsize = 0;
    int Key, Value;

    static {
        for (int i = 0; i < size; i++) {
            hash[i] = -1;
        }
    }

    // 構(gòu)造方法
    public HashDemo(int Key, int Value) {
        this.Key = Key;
        this.Value = Value;
    }

    public HashDemo() {}

    // 計(jì)算hashcode
    public int hashcode(int Key) {
        int index = Key % size;
        if (currsize == size) {
            return -1;
        } else {
            while (index >= 0 && index < size && hash[index] != -1) {
                index++;
                if (index == size - 1) {
                    index++;
                }
            }
            return index;
        }
    }


    // 往HashDemo中插入測試數(shù)據(jù)
    public boolean put(int Key, int Value) {
        int index = hashcode(Key);
        if (index == -1 || index < 0 || index >= size)
            return false;
        else {
            hash[index] = Value;
            return true;
        }
    }

    public void Tester() {
        HashDemo hd = new HashDemo();
        long starttime = System.currentTimeMillis();

        for (int i = 0; i < 100000; i++) {
            hd.put(i * i, i * i);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("100000次put所用時(shí)間:" + (endtime - starttime) + "ms");
            }

}

程序測試結(jié)果:

二、java中hashmap的具體實(shí)現(xiàn)

import java.util.HashMap;

public class HashTest {

    public void Tester(){
        HashMap<Integer,Integer> hm=new HashMap<Integer,Integer>();

        long starttime=System.currentTimeMillis();

        for(int i=0;i<1000000;i++){
            Integer n=new Integer(i);
            hm.put(n*n,n*n );
        }

        long endtime=System.currentTimeMillis();
        System.out.println("100000次put所用時(shí)間:"+(endtime-starttime)+"ms");

        starttime=System.currentTimeMillis();

        for(int i=0;i<1000000;i++){
            Integer n=new Integer(i);
            Integer m=hm.get(n*n);
        }

        endtime=System.currentTimeMillis();
        System.out.println("100000次get所用時(shí)間:"+(endtime-starttime)+"ms");

        starttime=System.currentTimeMillis();

        for(int i=0;i<1000000;i++){
            Integer n=new Integer(i);
            hm.remove(n*n);
        }

        endtime=System.currentTimeMillis();
        System.out.println("100000次remove所用時(shí)間:"+(endtime-starttime)+"ms");
    }

測試結(jié)果:

可以看到使用java中自帶的hashmap類執(zhí)行put操作時(shí),和上述思路所花費(fèi)的時(shí)間有較大的出入,并且可以發(fā)現(xiàn)多次put和get操作所花費(fèi)的時(shí)間也有較大的差別。

通過查看源代碼其實(shí)不難發(fā)現(xiàn),java中的哈希表中每一個(gè)位置不會(huì)只存儲(chǔ)一個(gè)元素,如果有多個(gè)Key值計(jì)算出來的hashcode結(jié)果是相同的,則這幾個(gè)元素并不會(huì)移動(dòng)存儲(chǔ)的位置,也就是說,hashcode一旦被計(jì)算出來,就不會(huì)在改變。

那么多個(gè)數(shù)據(jù)是怎么存儲(chǔ)在數(shù)組的一個(gè)位置上呢,其實(shí)很簡單,我們可以聯(lián)想數(shù)據(jù)結(jié)構(gòu)中的“圖”,其中有一種表示方法叫做臨接表表示法,將存儲(chǔ)在同一位置的數(shù)據(jù)用鏈表的形式連接起來來進(jìn)行存儲(chǔ),其實(shí)HashMap有一個(gè)叫做Entry的內(nèi)部類,它用來存儲(chǔ)key-value對。

```

如圖所示:

由于put時(shí)每一次都要實(shí)例化Entry內(nèi)部類的對象,所以put方法要使用比get方法更久的時(shí)間。

三、hashcode的計(jì)算方法

由于java中有許多的數(shù)據(jù)類型,而且有時(shí)傳入的Key是一個(gè)類的對象。所以hashcode的計(jì)算并不是那么容易。在設(shè)計(jì)一個(gè)類的時(shí)候,很可能要重寫類的hashCode()方法,根據(jù)哈希表的特點(diǎn),重寫的hashCode()方法需要遵守以下準(zhǔn)則:
            ①同一個(gè)對象調(diào)用hashCode()時(shí),應(yīng)返回相同的值
            ②若兩個(gè)對象通過equals()方法比較返回true的時(shí)候,兩個(gè)對象的hashCode()方法應(yīng)返回相同的值
            ③對象調(diào)用equals()方法參與比較的值,都應(yīng)該拿來計(jì)算hashCode()

對象中不同的值對應(yīng)不同的計(jì)算方法:

```

將所有的數(shù)據(jù)計(jì)算出來的hashCode相加即為該對象的hashCode();為了避免重復(fù),可以讓各個(gè)數(shù)據(jù)乘以不同的權(quán)值后再相加。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产一级内射麻豆91| 日本亚洲精品在线观看| 中文字幕人妻av不卡| 日韩人妻免费视频一专区| 日韩精品一区二区毛片| 日韩综合国产欧美一区| 少妇人妻无一区二区三区| 亚洲国产精品久久综合网| 国产精品国产亚洲看不卡| 精品一区二区三区乱码中文| 国产av一区二区三区久久不卡| 高清欧美大片免费在线观看| 亚洲熟女乱色一区二区三区| 欧美国产日产在线观看| 亚洲精选91福利在线观看 | 免费特黄欧美亚洲黄片| 日韩人妻毛片中文字幕| 午夜资源在线观看免费高清| 日韩成人动画在线观看| 欧美日本亚欧在线观看| 国产自拍欧美日韩在线观看| 制服丝袜美腿美女一区二区| 久久大香蕉精品在线观看| 日韩一区中文免费视频| av在线免费观看一区二区三区| 亚洲日本韩国一区二区三区| 人妻精品一区二区三区视频免精| 国产日韩欧美综合视频| 国产精品一区二区不卡中文| 国产成人亚洲综合色就色| 九九热九九热九九热九九热| 日系韩系还是欧美久久| 欧美人妻盗摄日韩偷拍| 日韩人妻免费视频一专区| 日韩欧美国产精品自拍| 91欧美激情在线视频| 亚洲欧美日韩国产成人| 午夜久久精品福利视频| 欧美一区二区三区在线播放| 中文字幕中文字幕一区二区| 日韩成人动画在线观看|