ConcurrentHashMap源碼閱讀補(bǔ)充1——為什么使用Treebin而不是現(xiàn)成TreeMap等浴讯?

1.官方文檔的說(shuō)明

參考先前ConcurrentHashMap類(lèi)實(shí)現(xiàn)說(shuō)明翻譯:

TreeBins use a special form of comparison for search and
related operations (which is the main reason we cannot use
existing collections such as TreeMaps). TreeBins contain
Comparable elements, but may contain others, as well as
elements that are Comparable but not necessarily Comparable for
the same T, so we cannot invoke compareTo among them. To handle
this, the tree is ordered primarily by hash value, then by
Comparable.compareTo order if applicable.  On lookup at a node,
if elements are not comparable or compare as 0 then both left
and right children may need to be searched in the case of tied
hash values. (This corresponds to the full list search that
would be necessary if all elements were non-Comparable and had
tied hashes.) On insertion, to keep a total ordering (or as
close as is required here) across rebalancings, we compare
classes and identityHashCodes as tie-breakers. The red-black
balancing code is updated from pre-jdk-collections
(http://gee.cs.oswego.edu/dl/classes/collections/RBCell.java)
based in turn on Cormen, Leiserson, and Rivest "Introduction to
Algorithms" (CLR).

Treebins在搜索和相關(guān)操作中使用了特殊形式的比較(這也是不能使用現(xiàn)存集合例如TreeMap的主要原因)脖母。Treebins包含Comparable元素疆导,但是也可能包含其他類(lèi)型的(不能調(diào)用compareTo的元素)蟆沫。

2.看看TreeMap對(duì)元素的要求

The map is sorted according to the Comparable natural
ordering of its keys, or by a  Comparator provided at map
creation time, depending on which constructor is used.
  • 要么元素是Comparable類(lèi)型的
  • 要么提供一個(gè)比價(jià)器Comparator

其部分put代碼如下:

    public V put(K key, V value) {
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
             ...
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);

可見(jiàn)在插入元素時(shí)歉秫,要么調(diào)用比較器comparator的compara蛾洛,要么調(diào)用compareTo方法確定元素要插入紅黑樹(shù)的位置。

所以這里有一個(gè)核心區(qū)別:對(duì)于TreeMap雁芙,是一個(gè)SortedMap轧膘,本質(zhì)上是針對(duì)有序、可排序元素使用的兔甘。而ConcurrentHashMap是一個(gè)HashMap谎碍,本質(zhì)上并不要求元素有序,而是為了存儲(chǔ)鍵值對(duì)而已洞焙,只不過(guò)為了更快的存取蟆淀。因此,必然不要求其有序澡匪。另外存儲(chǔ)的元素是Comparable時(shí)熔任,但可能不是同一種類(lèi)型的。例如Integer和Double唁情。

public class CHMTest {

    public static void main(String[] args) {
//        Map<Number, String>  map =  new ConcurrentHashMap<>();
        Map<Number, String>  map =  new TreeMap<>();
        map.put(12, "12");
        map.put(13.0, "13");
        System.out.println(map);
    }
}

使用TreeMap時(shí)結(jié)果會(huì)拋出異常:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
    at java.lang.Double.compareTo(Double.java:49)
    at java.util.TreeMap.put(TreeMap.java:568)
    at com.enjoy.learn.core.concurrency.CHMTest.main(CHMTest.java:21)

因?yàn)檎{(diào)用Double.compareTo時(shí)疑苔,會(huì)對(duì)入?yún)nteger進(jìn)行轉(zhuǎn)型,但是Double和Integer不屬于父子類(lèi)關(guān)系荠瘪。


但是顯然ConcurrentHashMap是可以的:

    public static void main(String[] args) {
        Map<Number, String>  map =  new ConcurrentHashMap<>();
//        Map<Number, String>  map =  new TreeMap<>();
        map.put(12, "12");
        map.put(13.0, "13");
        System.out.println(map);
    }

結(jié)果:

{13.0=13, 12=12}

所以其紅黑樹(shù)為了兼容這種表現(xiàn),必須進(jìn)行改進(jìn)赛惩,使得能夠放入任意鍵值對(duì)哀墓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市喷兼,隨后出現(xiàn)的幾起案子篮绰,更是在濱河造成了極大的恐慌,老刑警劉巖季惯,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吠各,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡勉抓,警方通過(guò)查閱死者的電腦和手機(jī)贾漏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)藕筋,“玉大人纵散,你說(shuō)我怎么就攤上這事。” “怎么了伍掀?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵掰茶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蜜笤,道長(zhǎng)濒蒋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任把兔,我火速辦了婚禮沪伙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垛贤。我一直安慰自己焰坪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布聘惦。 她就那樣靜靜地躺著某饰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪善绎。 梳的紋絲不亂的頭發(fā)上黔漂,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音禀酱,去河邊找鬼炬守。 笑死,一個(gè)胖子當(dāng)著我的面吹牛剂跟,可吹牛的內(nèi)容都是我干的减途。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼曹洽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鳍置!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起送淆,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤税产,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后偷崩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辟拷,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年阐斜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衫冻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谒出,死狀恐怖羽杰,靈堂內(nèi)的尸體忽然破棺而出渡紫,到底是詐尸還是另有隱情,我是刑警寧澤考赛,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布惕澎,位于F島的核電站,受9級(jí)特大地震影響颜骤,放射性物質(zhì)發(fā)生泄漏唧喉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一忍抽、第九天 我趴在偏房一處隱蔽的房頂上張望八孝。 院中可真熱鬧,春花似錦鸠项、人聲如沸干跛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)楼入。三九已至,卻和暖如春牧抽,著一層夾襖步出監(jiān)牢的瞬間嘉熊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工扬舒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阐肤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓讲坎,卻偏偏與公主長(zhǎng)得像孕惜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晨炕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350