对于常用的集合大家都不陌生,但是深入到内部原理可能都是一知半解,通过阅读源码理解如下。
ArrayList
ArrayList内部就是一个默认大小为10的动态对象数组容器,每当add一个新数据的时候,如果大于原来的容器大小,则会通过Arrays.copyOf把容器大小增加到原来的1.5倍,以此类推。当可以预知数据大小,可以通过initialCapacity来默认设置动态数据的大小,减少扩容带来的资源消耗。
时间复杂度:
get() - 直接读取下标 - O(1)
add(E) - 直接在后面添加 - O(1)
add(idnex, E) - 插入数据后需要移动后面的数据 - O(n)
remove(index) - 删除后需要移动 - O(n)
LinkedList
LinkedList内部是一个双向链表,add新数据的时候,其实就是调用linklast在链表尾部插入数据。删除的时候直接找到对应数据,替换掉链表的前后节点即可。
时间复杂度:
get() - 需要遍历 - O(n)
add(E) - 调用linklast直接添加在最后 - O(1)
add(index, E) - 需要先查找到原来index位置的数据,再重新指定链表前后的数据 - O(n)
remove() - 直接调用removeLast删除最后数据 - O(1)
remove(index) - 需要先查找到原来index位置的数据 - O(n)
HashMap
HashMap内部其实是一个数组,每个数组下是一个单向链表。HashMap中的数组是一个取名为Entry的类,类包含(key, value, next)这几个属性。存放规则为,数组下标按hash(key)%len获得,取得数组后则查找对应数组的值。HashMap还有个负载因子(默认0.75),当里面数组填满了75%的时候,会进行扩展到原来大小的2倍。
那么问题来了,如果在put的时候,取到hash(key)%len的值相等时不就冲突了?HashMap的处理方法是:原来有一个Entry[0] = A,此时来一个index也是0的B,则会把Entry[0] = B,B.next = A,又来一个C的时候,则会把Entry[0] = C,C.next = B,以此类推。这样Entry就会形成一个链表,取的时候则是遍历链表取值。
这里需要提到的是,使用hashMap的时候,引入的key对象必须重写hashCode()和equal()两个函数,原因可以参考源码判断条件(if (e.hash == hash && ((k = e.key) == key || key.equals(k)))),如果hashCode()没重写,则压根找不到对应数组,如果equal()没重写,则无法判断key值的内容是否相等。
public V put(K key, V value) { if (key == null) return putForNullKey(value); //null总是放在数组的第一个链表中 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); //遍历链表 for (Entry<k> e = table[i]; e != null; e = e.next) { Object k; //如果key在链表中已存在,则替换为新value if (e.hash == hash && ((k = e.key) == key || key.equals(k))){ V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }</k>
补充:
在java8之后hashmap进行了优化:由于单向链表的查询时间复杂度为O(n),在极端情况下可能存在性能问题,于是java8针对链表长度大于8的情况会使用时间复杂度为O(log n)的红黑树进行存储来提升存储查询的效率。
LinkedHashMap
LinkedHashMap内部双向链表和HashMap的结合,支持多种迭代顺序,默认按插入顺序,也可以按访问顺序。
访问顺序(accessOrder=true):调用过get访问的元素会放到链尾,迭代会从链首开始
插入顺序(accessOrder=false):按插入顺序迭代出来
TreeMap
TreeMap内部是基于红黑树实现的,并且默认会通过compareTo按照key类型进行自然排序。TreeSet的低层是TreeMap。
以上是解析JAVA 常用集合內部機制原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

本文解釋了用於構建分佈式應用程序的Java的遠程方法調用(RMI)。 它詳細介紹了接口定義,實現,註冊表設置和客戶端調用,以解決網絡問題和安全性等挑戰。

本文詳細介紹了用於網絡通信的Java的套接字API,涵蓋了客戶服務器設置,數據處理和關鍵考慮因素,例如資源管理,錯誤處理和安全性。 它還探索了性能優化技術,我

本文詳細介紹了創建自定義Java網絡協議。 它涵蓋協議定義(數據結構,框架,錯誤處理,版本控制),實現(使用插座),數據序列化和最佳實踐(效率,安全性,維護


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver Mac版
視覺化網頁開發工具

記事本++7.3.1
好用且免費的程式碼編輯器