日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

JDK 7的算法和数据结构

發(fā)布時(shí)間:2023/12/3 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JDK 7的算法和数据结构 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在定期檢查JDK中是否存在一種或另一種標(biāo)準(zhǔn)算法時(shí),我決定進(jìn)行這種索引。 有趣的是,為什么其中包含一些著名的數(shù)據(jù)結(jié)構(gòu)或算法,而另一些卻沒(méi)有? 此調(diào)查的格式僅涉及JDK的算法和數(shù)據(jù)結(jié)構(gòu)的關(guān)鍵特性和功能,所有詳細(xì)信息和完整描述-您可以在javadoc或jdk源代碼中輕松找到。 讓我們從簡(jiǎn)單開(kāi)始到復(fù)雜!

JDK的數(shù)據(jù)結(jié)構(gòu)

jdk中有一個(gè)堆棧 ,它是從堆棧中出現(xiàn)的-類Stack ,但不建議使用它,它很復(fù)雜又很奇怪:它繼承自Vector ,因此基于Dynamic Array并已同步。 為什么一個(gè)簡(jiǎn)單的棧需要這一切,為什么它不只是一個(gè)接口-目前尚不清楚(討論過(guò)很多次: 1 , 2 ),但似乎只是一個(gè)架構(gòu)的錯(cuò)誤,同樣與載體本身。 順便說(shuō)一句,JDK作者自己建議使用Deque 。

Deque – 雙端隊(duì)列的接口(api)(O中的LIFO + FIFO(1)),其中包括堆棧操作(push,pop,isEmpty,size),并且到目前為止在jdk中可用(1.6+) 。 當(dāng)然,將這些堆棧操作放在接口Stack中會(huì)更合乎邏輯,例如讓Deque繼承它,但是由于Stack已經(jīng)存在,并且向后兼容性是Java的“圣杯” –他們不得不犧牲常規(guī)設(shè)計(jì)。 Deque的實(shí)現(xiàn)是ArrayDeque和LinkedList ,它們也是常規(guī)隊(duì)列的實(shí)現(xiàn)者–因此我們將在后面討論。

隊(duì)列

接下來(lái),讓我們看一下隊(duì)列數(shù)據(jù)類型 。 這里的一切都很好,設(shè)計(jì)得很好。 隊(duì)列 – FIFO隊(duì)列的接口(api),以恒定時(shí)間O(1)添加到開(kāi)頭并從結(jié)尾刪除。

主要實(shí)現(xiàn)有: ArrayDeque ,基于動(dòng)態(tài)可擴(kuò)展數(shù)組的循環(huán)緩沖區(qū) (填充時(shí)加倍)和LinkedList ( 經(jīng)典的雙向鏈接列表) (大小不受限制)。 令人驚訝的是,第一個(gè)不支持隨機(jī)訪問(wèn) (使用索引添加/刪除/獲取),第二個(gè)卻支持O(n)時(shí)間并通過(guò)鏈表進(jìn)行迭代。 這些類還實(shí)現(xiàn)了上述Deque,因此它們支持從末尾移除并在恒定時(shí)間內(nèi)添加到頂部。

接下來(lái),從jdk 1.5+開(kāi)始,添加了PriorityQueue ,這實(shí)際上違反了合同,因?yàn)殛?duì)列元素不是從末尾檢索的(并且也不添加到頭部),而是根據(jù)優(yōu)先級(jí)檢索的。 PriorityQueue基于可擴(kuò)展的二進(jìn)制堆 ,其頂部最小(根據(jù)其比較器),并且在填充時(shí)提高了1.5倍。 關(guān)鍵特征分別是:元素的添加/刪除在O(log N)中,而對(duì)最小值(標(biāo)頭)的引用在O(1)中。

其他類型的隊(duì)列是為多線程使用而設(shè)計(jì)的,它們是: BlockingQueue , TransferQueue , ConcurrentLinkedQueue和ConcurrentLinkedDeque 。

BlockingQueue ( ArrayBlockingQueue , LinkedBlockingQueue , PriorityBlockingQueue )的實(shí)現(xiàn)是其原始版本的一種同步版本,即幾乎每個(gè)操作都是串行執(zhí)行的(具有獨(dú)占鎖定)。 對(duì)于DelayQueue也是如此:也是同步的,并且在內(nèi)部使用PriorityQueue 。

其他實(shí)現(xiàn): SynchronousQueue , TransferQueue ( LinkedTransferQueue ), ConcurrentLinkedQueue , ConcurrentLinkedDeque –基于不同的方法:它們使用基于鏈表和CAS指令的非阻塞隊(duì)列算法,這些算法在多處理器環(huán)境中可以很好地并行化。 詳細(xì)描述在源代碼中。

這類算法的理論是一個(gè)非常龐大且現(xiàn)代的話題,因此還沒(méi)有很好的標(biāo)準(zhǔn)化和結(jié)構(gòu)化,它們超出了本文的討論范圍,也不屬于另一篇文章的主題。

優(yōu)先隊(duì)列

就像從jdk 1.5+開(kāi)始所說(shuō)的那樣,有一個(gè)通用的PriorityQueue根據(jù)元素比較器工作。 而且,jdk中還有堆的另一種實(shí)現(xiàn)。 這是很好的舊Timer ,它是內(nèi)部類– TaskQueue(頂部的延遲最小的任務(wù))。 當(dāng)然,這是一個(gè)私有類,除了在Timer內(nèi)部,不能使用。

清單

如您所知,有順序和/或隨機(jī)訪問(wèn)類型列表。 在Java中,它是List ,主要有2種實(shí)現(xiàn):首先-是ArrayList ,支持隨機(jī)訪問(wèn) ,基于動(dòng)態(tài)可擴(kuò)展數(shù)組 (填充時(shí)增加一半),但是在刪除所有元素后不會(huì)縮小,您需要調(diào)用a特殊方法( trimToSize )。

第二個(gè)-再次是LinkedList,它是一個(gè)雙鏈表順序訪問(wèn)大小,僅受jvm的內(nèi)存限制。 盡管也存在隨機(jī)訪問(wèn)(索引)的方法–如前所述,它們需要O(n)時(shí)間。

因此,java集合中沒(méi)有最簡(jiǎn)單的鏈表實(shí)現(xiàn),盡管這是一個(gè)好主意(鏈接的開(kāi)銷減少了2倍),并且沒(méi)有簡(jiǎn)單的堆棧。

要在多線程環(huán)境中使用列表,有幾個(gè)選項(xiàng): CopyOnWriteArrayList (更改操作– O(n)),包裝器( synchonizedList )以及過(guò)時(shí)的Vector 。

符號(hào)表

它們?cè)贘DK中顯示為二進(jìn)制樹(shù)和哈希表。 二叉樹(shù) –它是TreeMap (或TreeSet ), SortedMap (也是SortedSet)的實(shí)現(xiàn),它基于經(jīng)典的紅黑樹(shù) ,即是平衡的,并且對(duì)于O(log N)保證了其基本操作,并且不限大小。 jdk中不存在其他類型的樹(shù)。

哈希表是HashMap (也是HashSet ),它可能是Java中最常用的結(jié)構(gòu),它基于可動(dòng)態(tài)擴(kuò)展的哈希表,具有與鏈表的單獨(dú)鏈接 ,具有所有功能:性能取決于哈希函數(shù)的質(zhì)量,因此最壞的情況是O(N)。 當(dāng)大小達(dá)到預(yù)定的loadFactor時(shí), HashMap的大小將增加一倍。 值得注意的是,為了保護(hù)錯(cuò)誤的哈希函數(shù),使用了雙哈希,并且對(duì)調(diào)用hashCode()的結(jié)果應(yīng)用了棘手的位算法。

在JDK中,也有帶有開(kāi)放地址(線性探測(cè))的哈希表實(shí)現(xiàn)。 其中之一是IdentityHashMap ,當(dāng)鍵和值都存儲(chǔ)在彼此相鄰的同一數(shù)組中時(shí),它會(huì)使用經(jīng)典線性探測(cè)的優(yōu)化版本,以實(shí)現(xiàn)更好的數(shù)據(jù)緩存(javadoc:?大型表的局部性比使用單獨(dú)的數(shù)組?)

第二種開(kāi)放尋址實(shí)現(xiàn)是非常特定的:它僅用于存儲(chǔ)ThreadLocal元素( ThreadLocalMap中的內(nèi)部隱藏類),當(dāng)然不可用。

還有多線程版本: ConcurrentHashMap中 ,包裝synchronizedMap , 哈希表和ConcurrentSkipListMap 。 包裝器-自然只是阻止了常規(guī)HashMap Hashtable的版本-同一件事(并且是舊的,不建議使用), ConcurrentHashMap-鎖條版本,減少了關(guān)鍵的鎖部分(最好閱讀JCiP ,這里是( 摘錄 ) ConcurrentSkipListMap –是哈希表的非阻塞命名算法的改編版本(有關(guān)詳細(xì)信息,請(qǐng)參見(jiàn)源代碼)。

集合(不包含重復(fù)項(xiàng))–在Java中設(shè)置 ,并通過(guò)HashMap實(shí)現(xiàn),因此所有被稱為哈希表的對(duì)象–對(duì)HashSet有效。

圖表

圖結(jié)構(gòu)和算法未在jdk中表示。 因此,您只能為此使用第三方庫(kù)。

弦樂(lè)

java中通常有一個(gè)字符串實(shí)現(xiàn):基于unicode字符數(shù)組。 值得一提的是,從1.7_17版本開(kāi)始,由于已復(fù)制子字符串,因此子字符串的性能為O(n)。

有趣的是, 此實(shí)現(xiàn)使用了一種簡(jiǎn)單的(強(qiáng)力)子字符串搜索算法,該算法在最壞的情況下以O(shè)(N * M)運(yùn)行,并且沒(méi)有一些有效的算法(在有限狀態(tài)機(jī)上構(gòu)建:Knuth-Morris-Pratt等) 。

原因有幾個(gè):字母UTF字符大(?65K),因此存儲(chǔ)狀態(tài)機(jī)的開(kāi)銷很大,而就采用了蠻力算法(不使用額外的內(nèi)存)。 其次,在平均輸入字符串上–根據(jù)統(tǒng)計(jì)數(shù)據(jù),該算法與其他算法相比并沒(méi)有很多。

與排序相同:有有效的基數(shù)排序字符串a(chǎn)lgs(LSD,MSD等),但是在jdk中,有一個(gè)用于字符串的標(biāo)準(zhǔn)對(duì)象排序 ,如果運(yùn)行,則以O(shè)(M * N * log N)運(yùn)行大部分線相差不大(M –線長(zhǎng))。 原因是相同的:快速計(jì)數(shù)字符串算法需要額外的UTF字母大小的數(shù)組,這使得它們?cè)谄骄斎肷戏浅o(wú)效。

JDK算法

排序

由于jdk7發(fā)生了許多有關(guān)各種選項(xiàng)的更改,因此討論了很多次,關(guān)于此主題的信息和文章很多,您可以輕松地將其搜索出來(lái)。

簡(jiǎn)而言之,這是jdk中排序?qū)崿F(xiàn)的實(shí)際列表: TimSort –默認(rèn)情況下對(duì)對(duì)象進(jìn)行排序; mergesort –還用于對(duì)象;舊版本(通過(guò)系統(tǒng)屬性啟用); Dual-Pivot Quick sort –用于基元;然后按計(jì)數(shù)排序用于字節(jié)/字符數(shù)組,最后插入排序用于任何情況下使用的小數(shù)組。

集合內(nèi)容使用Collections.sort(List…)進(jìn)行排序,仍然可以通過(guò)將集合復(fù)制到數(shù)組中,對(duì)其進(jìn)行排序,然后相應(yīng)地覆蓋集合內(nèi)容來(lái)完成。 因此,盡管沒(méi)有開(kāi)銷,對(duì)集合進(jìn)行排序仍然是不可能的,盡管我認(rèn)為擁有就地排序的鏈表是一個(gè)好主意。 Java中的字符串排序也使用對(duì)象版本完成,原因已經(jīng)提到。

正在搜尋

對(duì)于原語(yǔ)和對(duì)象的所有數(shù)組以及隨機(jī)訪問(wèn)列表實(shí)現(xiàn)(例如ArrayList等),都存在傳統(tǒng)的二進(jìn)制搜索 。 此外,JDK中還有一個(gè)二進(jìn)制搜索鏈接列表的版本! 令人驚訝的是:JDK沒(méi)有對(duì)鏈表進(jìn)行排序,但是對(duì)它們進(jìn)行二進(jìn)制搜索! 盡管沒(méi)有太大意義,因?yàn)檫@種版本的性能為O(N)。

常用表達(dá)

為此提供了Pattern和Matcher類。 Java使用基于帶回溯的非確定性有限狀態(tài)機(jī)( NFA )的傳統(tǒng)實(shí)現(xiàn)。 因此,在退化的輸入上,在最壞的情況下它給出了指數(shù)復(fù)雜度 O(m ^ N),例如,在Java中運(yùn)行此regexp并嘗試添加/刪除“ a”符號(hào):“ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aa )* b”)

此外,還有所謂的有序交替-此功能可在找到第一個(gè)匹配項(xiàng)后停止搜索,但不會(huì)顯示最具體(最長(zhǎng))的搜索結(jié)果( 例如 )。

哈希函數(shù),校驗(yàn)和

jdk中有hashCode實(shí)現(xiàn)的六個(gè)版本,并且Park-Miller_random_number_generator是默認(rèn)版本,其他很簡(jiǎn)單,例如常量或?qū)ο髢?nèi)存地址,并且不使用算法,您可以在c ++ jdk源代碼中找到它們。 MessageDigest類中還有行業(yè)標(biāo)準(zhǔn)的哈希算法(SHA-*,MD5和變體)。

對(duì)于校驗(yàn)和,有Adler-32 ( javadoc )和CRC32 ( javadoc )算法的實(shí)現(xiàn)。

壓縮

jdk中有一個(gè)標(biāo)準(zhǔn)的壓縮deflate( Deflater )算法的實(shí)現(xiàn),并且zip / gzip jdk utils使用它。 它們都在java.util.zip包中 。

摘要

如您所見(jiàn),經(jīng)典數(shù)據(jù)結(jié)構(gòu)并未完全用Java呈現(xiàn),但與此同時(shí),幾乎所有jdk中的所有數(shù)據(jù)結(jié)構(gòu)都可以使用很多線程安全版本。 缺少的是一個(gè)懸而未決的問(wèn)題。 例如,您可以爭(zhēng)辯jdk是否需要一些Union-Find,但是在社交網(wǎng)絡(luò)時(shí)代完全缺少該語(yǔ)言的圖形結(jié)構(gòu)和算法非常令人驚訝,并且實(shí)際上會(huì)產(chǎn)生許多錯(cuò)誤和自行車。

參考:來(lái)自我們JCG合作伙伴 Mikhail Baturov 的JDK 7的算法和數(shù)據(jù)結(jié)構(gòu),這是另一個(gè)俄羅斯編程人員.blog博客。

翻譯自: https://www.javacodegeeks.com/2013/07/algorithms-and-data-structures-of-jdk-7.html

總結(jié)

以上是生活随笔為你收集整理的JDK 7的算法和数据结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。