成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【碼藝雜談】Java中的相同與不同

xingqiba / 399人閱讀

摘要:如果根據(jù)方法得到兩個(gè)對(duì)象不相同,那么兩個(gè)對(duì)象的方法的結(jié)果不一定不相同,我們可以利用這一點(diǎn)來提高散列表的性能。最后回到文章開頭的問題,如何判斷兩個(gè)對(duì)象或值是否相同這個(gè)問題其實(shí)有兩方面的含義,一方面是判斷的方法,另一方面是判斷的效率。

Java中有很多場(chǎng)景需要判斷兩個(gè)對(duì)象或者兩個(gè)值,那么

判斷是否相同的依據(jù)是什么?

如何判斷是否相同呢?

為了解釋這個(gè)問題,我們從Java語言的根說起,那Java語言的根在哪里?我們知道Java是一種面向?qū)ο蟮木幊陶Z言,對(duì)象是類的實(shí)例,所有的類都隱式繼承Object類,那Object類就是所有類的父類,也就是我們所說的根。
Object類中方法不多,其中有兩個(gè)方法,一個(gè)叫equals,另一個(gè)叫hashCode;

JDK中對(duì)equals的定義是:

Indicates whether some other object is "equal to" this one.

意思是說equals方法是用來判斷兩個(gè)對(duì)象是否相同的,到這里是不是已經(jīng)得到了文章開始的問題答案了呢,其實(shí)只能說得到了三分之一的答案,再看equals方法的實(shí)現(xiàn),

public boolean equals(Object obj) {
        return (this == obj);
    }

代碼很簡(jiǎn)單,通過“== ”判斷兩個(gè)對(duì)象是否相同;這里就要解釋一下Java中“== ”符號(hào)的作用,文章開頭也說了Java是一種面向?qū)ο蟮木幊陶Z言,所以Java中全都是對(duì)象,這樣表述是否正確呢?應(yīng)該算不完全正確,因?yàn)镴ava中還有一類基本數(shù)據(jù)類型,比如byte、short、int、long、float、double、boolean;當(dāng)“== ”符號(hào)作用于基本數(shù)據(jù)類型時(shí),其比較的是值,當(dāng)==符號(hào)作用于類對(duì)象時(shí)其比較的是對(duì)象在堆內(nèi)存的地址。

顯然Object類的equals方法適用的是類對(duì)象;也就是equals比較的是對(duì)象的堆內(nèi)存地址,如果自定義的類不重寫Object的equals方法,那么比較這個(gè)類的兩個(gè)對(duì)象相當(dāng)于比較這兩個(gè)對(duì)象的堆內(nèi)存地址,實(shí)際情況是,很多自定義的類對(duì)象的比較并不想通過判斷對(duì)象的堆內(nèi)存地址判斷兩個(gè)對(duì)象是否相同,而需要定義一些符合業(yè)務(wù)需求的規(guī)則,也就是說需要重寫equals方法;比如String類就重寫了Object的equals方法,

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

說了半天都是在說equals方法,開頭還提到了hashCode方法,hashCode方法有什么作用呢?

Object類的hashCode方法定義如下,可以看出其是一個(gè)本地方法,該方法的解釋是“Returns a hash code value for the object.”

public native int hashCode();

hashCode方法的定義中描述了其general contract:

相同的對(duì)象每次執(zhí)行hashCode的結(jié)果是相同的,這里的相等是指通過equals比較相同。

如果根據(jù)equals方法得到兩個(gè)對(duì)象相同,那么這兩個(gè)對(duì)象的hashCode方法的結(jié)果也一定相同。

如果根據(jù)equals方法得到兩個(gè)對(duì)象不相同,那么兩個(gè)對(duì)象的hashCode方法的結(jié)果不一定不相同,我們可以利用這一點(diǎn)來提高散列表的性能。

hashCode方法的定義還有一句話:This method is supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.
這句話什么意思呢?直白一點(diǎn)就是hashCode方法只有在散列表中才有作用;那什么是散列表?下面是維基百科的定義:

In computing, a hash table (hash map) is a data structure that implements an associative array abstract data type, a structure that can map keys to values. A hash table uses a hash function to compute an index into an array of buckets or slots, from which the desired value can be found.

散列表是一個(gè)以空間換時(shí)間的數(shù)據(jù)結(jié)構(gòu),通過key查找value,通過一個(gè)計(jì)算hash值的函數(shù)得到每個(gè)key在結(jié)構(gòu)中的位置索引,通過位置索引能夠快速定位value。HashMap是Java語言中散列表的一種實(shí)現(xiàn),下面是HashMap的hash方法和put方法的源碼,

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

可以看到在計(jì)算key的散列值時(shí),用到了key的hashCode方法。

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node[] tab; Node p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
        ...
    }

當(dāng)網(wǎng)map中放值時(shí),如果key的hash值相等時(shí),用equals方法判斷key是否相等,如果相等說明key在map中存在,則用新的value替換當(dāng)前的value。說了這么多,到底想說明什么?我們反過來思考一下,如果沒有hashCode方法,我們判斷某個(gè)鍵是否已經(jīng)存在,要通過equals方法逐個(gè)比較這個(gè)key和map中的所有key,數(shù)據(jù)量小的情況下是可以接受的,如果數(shù)據(jù)量大,這個(gè)比較的開銷是難以接受的,這就體現(xiàn)出了hashCode的作用,不需要和map中所有的key逐個(gè)比較,只需要比較hash值相同的即可,大大減少了比較的時(shí)間。這里即用到了key的equals方法又用到了hashCode方法,如果自定義類按照業(yè)務(wù)邏輯重寫了equals方法,但沒有按照類似的邏輯重寫hashCode方法,key值是否重復(fù)的判斷結(jié)果就會(huì)有問題,所以一般情況下如果重寫了equals方法,一定要重寫hashCode方法。

最后回到文章開頭的問題,如何判斷兩個(gè)對(duì)象或值是否相同?這個(gè)問題其實(shí)有兩方面的含義,一方面是判斷的方法,另一方面是判斷的效率。

判斷的方法:equals方法和符號(hào)“== ”,分別用于對(duì)象和基本數(shù)據(jù)類型。

在需要判斷的數(shù)據(jù)量很大的情況下,用equals方法逐個(gè)比較效率是很低的,這時(shí)候hashCode方法就派上用場(chǎng)了,hashCode方法的定義決定了其一些特性,相同對(duì)象的hashCode方法返回的值是相等的,不同的對(duì)象的hashCode方法返回值不一定不相同,所以通過hashCode方法能夠大大縮小比較的范圍,提高比較的效率。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76608.html

相關(guān)文章

  • Stream流Lambda表達(dá)式(一) 雜談

    摘要:一流轉(zhuǎn)換為數(shù)組集合陳楊將流轉(zhuǎn)換為數(shù)組將流轉(zhuǎn)換為數(shù)組將流轉(zhuǎn)換為集合將流轉(zhuǎn)換為集合解析 一、流 轉(zhuǎn)換為數(shù)組、集合 package com.java.design.java8.Stream; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context...

    Harpsichord1207 評(píng)論0 收藏0
  • 雜談:漸進(jìn)增強(qiáng)優(yōu)雅降級(jí)

    摘要:而漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)兩種不同的開發(fā)流程,也是在我們項(xiàng)目初期做調(diào)研選型時(shí)會(huì)考慮的一個(gè)點(diǎn)。二者區(qū)別漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)只是看待同種事物的兩種觀點(diǎn)。漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)都關(guān)注于同一網(wǎng)站在不同設(shè)備里不同瀏覽器下的表現(xiàn)程度。 作為一名前端開發(fā)人員,最頭疼的莫過于瀏覽器兼容。遠(yuǎn)古時(shí)期萬惡的IE6,到現(xiàn)在CSS3不兼容的IE7/8.為了保證不同版本瀏覽器都有共同或更優(yōu)化的用戶體驗(yàn),前端搬磚的我們不得不與...

    hiyang 評(píng)論0 收藏0
  • 雜談:漸進(jìn)增強(qiáng)優(yōu)雅降級(jí)

    摘要:而漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)兩種不同的開發(fā)流程,也是在我們項(xiàng)目初期做調(diào)研選型時(shí)會(huì)考慮的一個(gè)點(diǎn)。二者區(qū)別漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)只是看待同種事物的兩種觀點(diǎn)。漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)都關(guān)注于同一網(wǎng)站在不同設(shè)備里不同瀏覽器下的表現(xiàn)程度。 作為一名前端開發(fā)人員,最頭疼的莫過于瀏覽器兼容。遠(yuǎn)古時(shí)期萬惡的IE6,到現(xiàn)在CSS3不兼容的IE7/8.為了保證不同版本瀏覽器都有共同或更優(yōu)化的用戶體驗(yàn),前端搬磚的我們不得不與...

    王軍 評(píng)論0 收藏0
  • 雜談:漸進(jìn)增強(qiáng)優(yōu)雅降級(jí)

    摘要:而漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)兩種不同的開發(fā)流程,也是在我們項(xiàng)目初期做調(diào)研選型時(shí)會(huì)考慮的一個(gè)點(diǎn)。二者區(qū)別漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)只是看待同種事物的兩種觀點(diǎn)。漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)都關(guān)注于同一網(wǎng)站在不同設(shè)備里不同瀏覽器下的表現(xiàn)程度。 作為一名前端開發(fā)人員,最頭疼的莫過于瀏覽器兼容。遠(yuǎn)古時(shí)期萬惡的IE6,到現(xiàn)在CSS3不兼容的IE7/8.為了保證不同版本瀏覽器都有共同或更優(yōu)化的用戶體驗(yàn),前端搬磚的我們不得不與...

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

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

0條評(píng)論

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