日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解HashMap和TreeMap的区别

發布時間:2024/2/28 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解HashMap和TreeMap的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • HashMap和TreeMap本質區別
  • 排序區別
  • Null值的區別
  • 性能區別
  • 共同點

深入理解HashMap和TreeMap的區別

簡介

HashMap和TreeMap是Map家族中非常常用的兩個類,兩個類在使用上和本質上有什么區別呢?本文將從這兩個方面進行深入的探討,希望能揭露其本質。

HashMap和TreeMap本質區別

先看HashMap的定義:

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable

再看TreeMap的定義:

public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, java.io.Serializable

從類的定義來看,HashMap和TreeMap都繼承自AbstractMap,不同的是HashMap實現的是Map接口,而TreeMap實現的是NavigableMap接口。NavigableMap是SortedMap的一種,實現了對Map中key的排序。

這樣兩者的第一個區別就出來了,TreeMap是排序的而HashMap不是。

再看看HashMap和TreeMap的構造函數的區別。

public HashMap(int initialCapacity, float loadFactor)

HashMap除了默認的無參構造函數之外,還可以接受兩個參數initialCapacity和loadFactor。

HashMap的底層結構是Node的數組:

transient Node<K,V>[] table

initialCapacity就是這個table的初始容量。如果大家不傳initialCapacity,HashMap提供了一個默認的值:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

當HashMap中存儲的數據過多的時候,table數組就會被裝滿,這時候就需要擴容,HashMap的擴容是以2的倍數來進行的。而loadFactor就指定了什么時候需要進行擴容操作。默認的loadFactor是0.75。

static final float DEFAULT_LOAD_FACTOR = 0.75f;

再來看幾個非常有趣的變量:

static final int TREEIFY_THRESHOLD = 8; static final int UNTREEIFY_THRESHOLD = 6; static final int MIN_TREEIFY_CAPACITY = 64;

上面的三個變量有什么用呢?在java 8之前,HashMap解決hashcode沖突的方法是采用鏈表的形式,為了提升效率,java 8將其轉成了TreeNode。什么時候會發送這個轉換呢?

這時候就要看這兩個變量TREEIFY_THRESHOLD和UNTREEIFY_THRESHOLD。

有的同學可能發現了,TREEIFY_THRESHOLD為什么比UNTREEIFY_THRESHOLD大2呢?其實這個問題我也不知道,但是你看源代碼的話,用到UNTREEIFY_THRESHOLD時候,都用的是<=,而用到TREEIFY_THRESHOLD的時候,都用的是>= TREEIFY_THRESHOLD - 1,所以這兩個變量在本質上是一樣的。

MIN_TREEIFY_CAPACITY表示的是如果table轉換TreeNode的最小容量,只有capacity >= MIN_TREEIFY_CAPACITY的時候才允許TreeNode的轉換。

TreeMap和HashMap不同的是,TreeMap的底層是一個Entry:

private transient Entry<K,V> root

他的實現是一個紅黑樹,方便用來遍歷和搜索。

TreeMap的構造函數可以傳入一個Comparator,實現自定義的比較方法。

public TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}

如果不提供自定義的比較方法,則使用的是key的natural order。

排序區別

我們講完兩者的本質之后,現在舉例說明,先看下兩者對排序的區別:

@Testpublic void withOrder(){Map<String, String> books = new HashMap<>();books.put("bob", "books");books.put("c", "concurrent");books.put("a", "a lock");log.info("{}",books);} @Testpublic void withOrder(){Map<String, String> books = new TreeMap<>();books.put("bob", "books");books.put("c", "concurrent");books.put("a", "a lock");log.info("{}",books);}

同樣的代碼,一個使用了HashMap,一個使用了TreeMap,我們會發現TreeMap輸出的結果是排好序的,而HashMap的輸出結果是不定的。

Null值的區別

HashMap可以允許一個null key和多個null value。而TreeMap不允許null key,但是可以允許多個null value。

@Testpublic void withNull() {Map<String, String> hashmap = new HashMap<>();hashmap.put(null, null);log.info("{}",hashmap);} @Testpublic void withNull() {Map<String, String> hashmap = new TreeMap<>();hashmap.put(null, null);log.info("{}",hashmap);}

HashMap會報出: NullPointerException。

性能區別

HashMap的底層是Array,所以HashMap在添加,查找,刪除等方法上面速度會非常快。而TreeMap的底層是一個Tree結構,所以速度會比較慢。

另外HashMap因為要保存一個Array,所以會造成空間的浪費,而TreeMap只保存要保持的節點,所以占用的空間比較小。

HashMap如果出現hash沖突的話,效率會變差,不過在java 8進行TreeNode轉換之后,效率有很大的提升。

TreeMap在添加和刪除節點的時候會進行重排序,會對性能有所影響。

共同點

兩者都不允許duplicate key,兩者都不是線程安全的。

本文的例子https://github.com/ddean2009/learn-java-collections

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

歡迎關注我的公眾號:程序那些事,更多精彩等著您!
更多內容請訪問 www.flydean.com

總結

以上是生活随笔為你收集整理的深入理解HashMap和TreeMap的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。