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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java 最快平衡几个值_Java 集合框架面试问题集锦

發(fā)布時(shí)間:2025/3/12 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 最快平衡几个值_Java 集合框架面试问题集锦 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java集合框架(例如基本的數(shù)據(jù)結(jié)構(gòu))里包含了最常見的Java常見面試問題。很好地理解集合框架,可以幫助你理解和利用Java的一些高級(jí)特性。下面是面試Java核心技術(shù)的一些很實(shí)用的問題。

Q:最常見的數(shù)據(jù)結(jié)構(gòu)有哪些,在哪些場景下應(yīng)用它們?

A. 大部分人都會(huì)遺漏樹和圖這兩種數(shù)據(jù)結(jié)構(gòu)。樹和圖都是很有用的數(shù)據(jù)結(jié)構(gòu)。如果你在回答中提及到它們的話,面試者可能會(huì)對(duì)你進(jìn)行進(jìn)一步進(jìn)行的考核。

Q:你如何自己實(shí)現(xiàn)List,Set和Map?

A:雖然Java已經(jīng)提供了這些接口的經(jīng)過實(shí)踐證明和測試過的實(shí)現(xiàn),但是面試者還是喜歡這樣問,來測試你對(duì)數(shù)據(jù)結(jié)構(gòu)的理解。我寫的《Core Java Career Essentials》一書中通過圖例和代碼詳細(xì)地講解了這些內(nèi)容。

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

數(shù)組是最常用的數(shù)據(jù)結(jié)構(gòu)。數(shù)組的特點(diǎn)是長度固定,可以用下標(biāo)索引,并且所有的元素的類型都是一致的。數(shù)組常用的場景有把:從數(shù)據(jù)庫里讀取雇員的信息存儲(chǔ)為EmployeeDetail[],把一個(gè)字符串轉(zhuǎn)換并存儲(chǔ)到一個(gè)字節(jié)數(shù)組中便于操作和處理,等等。盡量把數(shù)組封裝在一個(gè)類里,防止數(shù)據(jù)被錯(cuò)誤的操作弄亂。另外,這一點(diǎn)也適合其他的數(shù)據(jù)結(jié)構(gòu)。

列表和數(shù)組很相似,只不過它的大小可以改變。列表一般都是通過一個(gè)固定大小的數(shù)組來實(shí)現(xiàn)的,并且會(huì)在需要的時(shí)候自動(dòng)調(diào)整大小。列表里可以包含重復(fù)的元素。常用的場景有,添加一行新的項(xiàng)到訂單列表里,把所有過期的商品移出商品列表,等等。一般會(huì)把列表初始化成一個(gè)合適的大小,以減少調(diào)整大小的次數(shù)。

集合和列表很相似,不過它不能放重復(fù)的元素。當(dāng)你需要存儲(chǔ)不同的元素時(shí),你可以使用集合。

堆棧只允許對(duì)最后插入的元素進(jìn)行操作(也就是后進(jìn)先出,Last In First Out – LIFO)。如果你移除了棧頂?shù)脑?#xff0c;那么你可以操作倒數(shù)第二個(gè)元素,依次類推。這種后進(jìn)先出的方式是通過僅有的peek(),push()和pop()這幾個(gè)方法的強(qiáng)制性限制達(dá)到的。這種結(jié)構(gòu)在很多場景下都非常實(shí)用,例如解析像(4+2)*3這樣的數(shù)學(xué)表達(dá)式,把源碼中的方法和異常按照他們出現(xiàn)的順序放到堆棧中,檢查你的代碼看看小括號(hào)和花括號(hào)是不是匹配的,等等。

這種用堆棧來實(shí)現(xiàn)的后進(jìn)先出(LIFO)的機(jī)制在很多地方都非常實(shí)用。例如,表達(dá)式求值和語法解析,校驗(yàn)和解析XML,文本編輯器里的撤銷動(dòng)作,瀏覽器里的瀏覽記錄,等等。這里是一些關(guān)于堆棧的一些Java面試題。

隊(duì)列和堆棧有些相似,不同之處在于在隊(duì)列里第一個(gè)插入的元素也是第一個(gè)被刪除的元素(即是先進(jìn)先出)。這種先進(jìn)先出的結(jié)構(gòu)是通過只提供peek(),offer()和poll()這幾個(gè)方法來訪問數(shù)據(jù)進(jìn)行限制來達(dá)到的。例如,排隊(duì)等待公交車,銀行或者超市里的等待列隊(duì)等等,都是可以用隊(duì)列來表示。

這里是一個(gè)用多線程來訪問阻塞隊(duì)列的例子。

http://java-success.blogspot.com.au/2012/04/multi-threading-with-blocking-queues.html

鏈表是一種由多個(gè)節(jié)點(diǎn)組成的數(shù)據(jù)結(jié)構(gòu),并且每個(gè)節(jié)點(diǎn)包含有數(shù)據(jù)以及指向下一個(gè)節(jié)點(diǎn)的引用,在雙向鏈表里,還會(huì)有一個(gè)指向前一個(gè)節(jié)點(diǎn)的引用。例如,可以用單向鏈表和雙向鏈表來實(shí)現(xiàn)堆棧和隊(duì)列,因?yàn)殒湵淼膬啥硕际强梢赃M(jìn)行插入和刪除的動(dòng)作的。當(dāng)然,也會(huì)有在鏈表的中間頻繁插入和刪除節(jié)點(diǎn)的場景。Apache的類庫里提供了一個(gè)TreeList的實(shí)現(xiàn),它是鏈表的一個(gè)很好的替代,因?yàn)樗欢嗾加昧艘稽c(diǎn)內(nèi)存,但是性能比鏈表好很多。也就是說,從這點(diǎn)來看鏈表其實(shí)不是一個(gè)很好的選擇。

ArrayList是列表的一個(gè)很好的實(shí)現(xiàn)。相比較TreeList而言,ArrayList在除了在列表中間插入或者刪除元素的情況,其他操作都比TreeList快很多。TreeList的實(shí)現(xiàn)是在內(nèi)部使用了一個(gè)樹形的結(jié)構(gòu)來保證所有的插入和刪除動(dòng)作的復(fù)雜度都是O(log n)的。這種實(shí)現(xiàn)方式使得TreeList在頻繁插入和刪除元素的時(shí)候的性能遠(yuǎn)遠(yuǎn)高于ArrayList和LinkedList。

class Link { private int id; // data private String name; // data private Link next; // reference to next link}

HashMap的訪問時(shí)間接近穩(wěn)定,它是一種鍵值對(duì)映射的數(shù)據(jù)結(jié)構(gòu)。這個(gè)數(shù)據(jù)結(jié)構(gòu)是通過數(shù)組來實(shí)現(xiàn)的。它通過hash函數(shù)來給元素定位,并且用沖突檢測算法來處理被hash到同一位置的值。例如,保存雇員的信息可以用雇員的id來作為key,對(duì)從properties文件里讀入的屬性-屬性值可以用key/value對(duì)來保存,等等。HashMap在初始化的時(shí)候,給定一個(gè)合適的大小可以減少調(diào)整大小的次數(shù)。

樹是一種由節(jié)點(diǎn)組成的數(shù)據(jù)結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都包含數(shù)據(jù)元素,并且有一個(gè)或多個(gè)子節(jié)點(diǎn),每個(gè)子節(jié)點(diǎn)指向一個(gè)父節(jié)點(diǎn)(譯者注:除了根節(jié)點(diǎn))可以表示層級(jí)關(guān)系或者數(shù)據(jù)元素的順序關(guān)系。常用的場景有表示一個(gè)組織里的雇員層級(jí)關(guān)系,XML元素的層級(jí)關(guān)系,等等。如果樹的每個(gè)子節(jié)點(diǎn)最多有兩個(gè)葉子節(jié)點(diǎn),那么這種樹被稱為二叉樹。二叉樹是一種非常常用的樹形結(jié)構(gòu), 因?yàn)樗倪@種結(jié)構(gòu)使得節(jié)點(diǎn)的插入和刪除都非常高效。樹的邊表示從一個(gè)節(jié)點(diǎn)到另外一個(gè)節(jié)點(diǎn)的快捷路徑。

Java里面沒有直接提供樹的實(shí)現(xiàn),但是它很容易通過下面的方式來實(shí)現(xiàn)。只需要?jiǎng)?chuàng)建一個(gè)Node對(duì)象,里面包含一個(gè)指向葉子節(jié)點(diǎn)的ArrayList。

package bigo; import java.util.ArrayList;import java.util.List; public class Node { private String name; private List children = new ArrayList( ); private Node parent; public Node getParent( ) { return parent; } public void setParent(Node parent) { this.parent = parent; } public Node(String name) { this.name = name; } public void addChild(Node child) { children.add(child); } public void removeChild(Node child) { children.remove(child); } public String toString( ) { return name; } }

只要數(shù)據(jù)元素的關(guān)系可以表示成節(jié)點(diǎn)和邊的網(wǎng)狀結(jié)構(gòu)的話,就可以用圖來表示。樹是一種特殊的圖,它的所有節(jié)點(diǎn)都只能有一個(gè)父節(jié)點(diǎn)。和樹不同的是,圖的形狀是由實(shí)際問題或者問題的抽象來決定的。例如,圖中節(jié)點(diǎn)(或者頂點(diǎn))可以表示不同的城市,而圖的邊則可以表示兩個(gè)城市之間的航線。

在Java里構(gòu)造一個(gè)圖,你需要解決數(shù)據(jù)通過什么方式保存和訪問的問題。在圖里面也會(huì)用到上面提到的數(shù)據(jù)結(jié)構(gòu)。Java的API里沒有提供圖的實(shí)現(xiàn)。不過有很多第三方庫里提供了,例如JUNG,JGraphT,以及JDSL(不過好像不支持泛型)。《Core Java Career Essential》一書包含了用Java實(shí)現(xiàn)的可用示例。

Q:你對(duì)大O這個(gè)符號(hào)有什么了解呢,你是否可以根據(jù)不同的數(shù)據(jù)結(jié)構(gòu)舉出一些列子來?

A:大O符號(hào)可以表示一個(gè)算法的效率,也可以用來描述當(dāng)數(shù)據(jù)元素增加時(shí),最壞情況下的算法的性能。大O符號(hào)也可以用來衡量的性能,例如內(nèi)存消耗量。有時(shí)候你可能會(huì)為了減少內(nèi)存使用量而選擇一個(gè)比較慢的算法。大O符號(hào)可以表示在大量數(shù)據(jù)的情況下程序的性能。不過,對(duì)于程序在大量數(shù)據(jù)量下的性能的測量,唯一比較實(shí)際的方式是行用較大的數(shù)據(jù)集來進(jìn)行性能基準(zhǔn)測試,這樣可以把一些在大O復(fù)雜度分析里沒有考慮到的情況包含進(jìn)去,例如在虛擬內(nèi)存使用比較多的時(shí)候系統(tǒng)會(huì)發(fā)生換頁的情況。雖然基準(zhǔn)測試比大O符號(hào)表示的結(jié)果更加實(shí)際,但是它不適用于設(shè)計(jì)階段,所以在這個(gè)這時(shí)候大O復(fù)雜度分析是最合適的選擇。

各種數(shù)據(jù)結(jié)構(gòu)在搜索,插入和刪除算法上的性能都可以用下面方式表示:常量復(fù)雜度O(1),線性復(fù)雜度O(n),對(duì)數(shù)復(fù)雜度O(log n),指數(shù)復(fù)雜度O(c^n),多項(xiàng)式復(fù)雜度O(n^c),平方復(fù)雜度O(n^2)以及階乘復(fù)雜度O(n!),這里面的n都指的是數(shù)據(jù)結(jié)構(gòu)里的元素的數(shù)量。性能和內(nèi)存占用是可以相互權(quán)衡的。下面是一些示例。

示例1:在HashMap里查找一個(gè)元素的的時(shí)間復(fù)雜度是常量的,也即是O(1)。這是因?yàn)椴檎以厥褂玫氖枪:瘮?shù),并且計(jì)算一個(gè)哈希值的時(shí)間是不受HashMap里的元素的個(gè)數(shù)的影響的。

示例2:線性搜索一個(gè)數(shù)組,列表以及鏈表都是的復(fù)雜度線性的,也即是O(n),這是查找的時(shí)候需要遍歷整個(gè)列表。也就是說,如果一個(gè)列表的長度是原來的兩倍,那么搜索所花的時(shí)間也是原來的兩倍。

示例3:一個(gè)需要比較數(shù)組里的所有元素的排序算法的復(fù)雜度是多項(xiàng)式的,即是O(n^2)。這是因?yàn)橐粋€(gè)嵌套的for循環(huán)的復(fù)雜度是O(n^2)。在搜素算法里有這樣的例子。

示例4:二分搜索一個(gè)數(shù)組或者數(shù)組列表的復(fù)雜度是對(duì)數(shù)的,即是O(log n)。在鏈表里查詢一個(gè)節(jié)點(diǎn)的復(fù)雜度一般是O(n)。相比較數(shù)組鏈表和數(shù)組的O(log n)的性能而言,隨著元素?cái)?shù)量的增長,鏈表的O(n)的復(fù)雜度的性能就比較差了。對(duì)數(shù)的時(shí)間復(fù)雜度就是如果10個(gè)元素花費(fèi)的時(shí)間是x單位的話,100個(gè)元素最多花費(fèi)2x單位的時(shí)間,而10000個(gè)元素最多花費(fèi)4x個(gè)單位的時(shí)間。如果你在一個(gè)平面坐標(biāo)上畫出圖形的話,你會(huì)發(fā)現(xiàn)時(shí)間的增長沒有n(元素的個(gè)數(shù))快。

Q:HashMap和TreeMap在性能上有什么樣的差別呢?你比較傾向于使用哪一個(gè)?

A:一個(gè)平衡樹的性能是O(logn)。Java里的TreeMap用一個(gè)紅黑樹來保證key/value的排序。紅黑樹是平衡二叉樹。保證二叉樹的平衡性,使得插入,刪除和查找都比較快,時(shí)間復(fù)雜度都是O(log n)。不過它沒有HashMap快,HashMap的時(shí)間復(fù)雜度是O(1),但是TreeMap的優(yōu)點(diǎn)在于它里面鍵值是排過序的,這樣就提供了一些其他的很有用的功能。

Q:怎么去選擇該使用哪一個(gè)呢?

A:使用無序的HashSet和HashMap,還是使用有序的TreeSet和TreeMap,主要取決于你的實(shí)際使用場景,一定程度上還和數(shù)據(jù)的大小以及運(yùn)行環(huán)境有關(guān)。比較實(shí)際的一個(gè)原因是,如果插入和更新都比較頻繁的話,那么保證元素的有序可以提高快速和頻繁查找的性能。如果對(duì)于排序操作(例如產(chǎn)生一個(gè)報(bào)表合作者運(yùn)行一個(gè)批處理程序)的要求不是很頻繁的話,那么把數(shù)據(jù)以無序的方式存儲(chǔ),然后在需要排序的時(shí)候用Collections.sort(…)來進(jìn)行排序,會(huì)比用有序的方式來存儲(chǔ)可能會(huì)更加高效。這個(gè)只是一種可選的方式,沒人能給你一個(gè)確切的答案。即使是復(fù)雜度的理論,例如O(n),成立的前提也是在n足夠大的情況下。只要在n足夠小的情況下,就算是O(n)的算法也可能會(huì)比O(log n)的算法更加高效。另外,一個(gè)算法可能在AMD處理器上的速度比在Intel處理器上快。如果你的系統(tǒng)有交換區(qū)的話,那么你還要考慮磁盤的性能。唯一可以確定的性能測試途徑是用大小合適的數(shù)據(jù)來測試和衡量程序的性能和內(nèi)存使用量。在你所選擇的硬件上來測試這兩種指標(biāo),是最合適的方法。

Q:如何權(quán)衡是用無序的數(shù)組還是有序的數(shù)組呢?

A:有序數(shù)組最大的優(yōu)點(diǎn)在于n比較大的時(shí)候,搜索元素所花的時(shí)間O(log n)比無序素組所需要的時(shí)間O(n)要少很多。有序數(shù)組的缺點(diǎn)在于插入的時(shí)間開銷比較大(一般是O(n)),因?yàn)樗斜炔迦朐卮蟮闹刀家笠苿?dòng)。而無序數(shù)組的插入時(shí)間開銷是常量時(shí)間,也就是說,插入的速度和元素的數(shù)量無關(guān)。下面的代碼片段展示了向有序數(shù)組和無序數(shù)組插入元素。

插入元素到一個(gè)無序的數(shù)組里

package bigo; import java.util.Arrays; public class InsertingElementsToArray { public static void insertUnsortedArray(String toInsert) { String[ ] unsortedArray = { "A

總結(jié)

以上是生活随笔為你收集整理的java 最快平衡几个值_Java 集合框架面试问题集锦的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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