成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

【備戰(zhàn)春招/秋招系列】美團(tuán)Java面經(jīng)總結(jié)進(jìn)階篇 (附詳解答案)

chengjianhua / 998人閱讀

摘要:我在前面的文章中也提到了應(yīng)該怎么做自我介紹與項(xiàng)目介紹,詳情可以查看這篇文章備戰(zhàn)春招秋招系列初出茅廬的程序員該如何準(zhǔn)備面試。因此基于事件消息對(duì)象驅(qū)動(dòng)的業(yè)務(wù)架構(gòu)可以是一系列流程。


一 消息隊(duì)列MQ的套路

1.1 介紹一下消息隊(duì)列MQ的應(yīng)用場(chǎng)景/使用消息隊(duì)列的好處

①.通過異步處理提高系統(tǒng)性能

②.降低系統(tǒng)耦合性

1.2 那么使用消息隊(duì)列會(huì)帶來什么問題?考慮過這個(gè)問題嗎?

1.3 介紹一下你知道哪幾種消息隊(duì)列,該如何選擇呢?

1.4 關(guān)于消息隊(duì)列其他一些常見的問題展望

二 談?wù)?InnoDB 和 MyIsam 兩者的區(qū)別

2.1 兩者的對(duì)比

2.2 關(guān)于兩者的總結(jié)

三 聊聊 Java 中的集合吧!

3.1 Arraylist 與 LinkedList 有什么不同?(注意加上從數(shù)據(jù)結(jié)構(gòu)分析的內(nèi)容)

3.2 HashMap的底層實(shí)現(xiàn)

① JDK1.8之前

② JDK1.8之后

3.3 既然談到了紅黑樹,你給我手繪一個(gè)出來吧,然后簡單講一下自己對(duì)于紅黑樹的理解

3.4 紅黑樹這么優(yōu)秀,為何不直接使用紅黑樹得了?

3.5 HashMap 和 Hashtable 的區(qū)別/HashSet 和 HashMap 區(qū)別

該文已加入開源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識(shí))。地址:https://github.com/Snailclimb...

系列文章:

【備戰(zhàn)春招/秋招系列1】程序員的簡歷就該這樣寫

【備戰(zhàn)春招/秋招系列2】初出茅廬的程序員該如何準(zhǔn)備面試?

【備戰(zhàn)春招/秋招系列3】Java程序員必備書單

【備戰(zhàn)春招/秋招系列4】美團(tuán)面經(jīng)總結(jié)基礎(chǔ)篇 (附詳解答案)

這是我總結(jié)的美團(tuán)面經(jīng)的進(jìn)階篇,后面還有終結(jié)篇哦!下面只是我從很多份美團(tuán)面經(jīng)中總結(jié)的在美團(tuán)面試中一些常見的問題。不同于個(gè)人面經(jīng),這份面經(jīng)具有普適性。每次面試必備的自我介紹、項(xiàng)目介紹這些東西,大家可以自己私下好好思考。我在前面的文章中也提到了應(yīng)該怎么做自我介紹與項(xiàng)目介紹,詳情可以查看這篇文章:【備戰(zhàn)春招/秋招系列2】初出茅廬的程序員該如何準(zhǔn)備面試?。

有人私信我讓我對(duì)美團(tuán)面試難度做一個(gè)評(píng)級(jí),我覺得如果有10級(jí)的話,美團(tuán)面試的難度大概在6級(jí)左右吧!部分情況可能因人而異了。

消息隊(duì)列/消息中間件應(yīng)該是Java程序員必備的一個(gè)技能了,如果你之前沒接觸過消息隊(duì)列的話,建議先去百度一下某某消息隊(duì)列入門,然后花2個(gè)小時(shí)就差不多可以學(xué)會(huì)任何一種消息隊(duì)列的使用了。如果說僅僅學(xué)會(huì)使用是萬萬不夠的,在實(shí)際生產(chǎn)環(huán)境還要考慮消息丟失等等情況。關(guān)于消息隊(duì)列面試相關(guān)的問題,推薦大家也可以看一下視頻《Java工程師面試突擊第1季-中華石杉老師》,如果大家沒有資源的話,可以在我的公眾號(hào)“Java面試通關(guān)手冊(cè)”后臺(tái)回復(fù)關(guān)鍵字“1”即可!
一 消息隊(duì)列MQ的套路
面試官一般會(huì)先問你這個(gè)問題,預(yù)熱一下,看你知道消息隊(duì)列不,一般在第一面的時(shí)候面試官可能只會(huì)問消息隊(duì)列MQ的應(yīng)用場(chǎng)景/使用消息隊(duì)列的好處、使用消息隊(duì)列會(huì)帶來什么問題、消息隊(duì)列的技術(shù)選型這幾個(gè)問題,不會(huì)太深究下去,在后面的第二輪/第三輪技術(shù)面試中可能會(huì)深入問一下。
1.1 介紹一下消息隊(duì)列MQ的應(yīng)用場(chǎng)景/使用消息隊(duì)列的好處

《大型網(wǎng)站技術(shù)架構(gòu)》第四章和第七章均有提到消息隊(duì)列對(duì)應(yīng)用性能及擴(kuò)展性的提升。

①.通過異步處理提高系統(tǒng)性能


如上圖,在不使用消息隊(duì)列服務(wù)器的時(shí)候,用戶的請(qǐng)求數(shù)據(jù)直接寫入數(shù)據(jù)庫,在高并發(fā)的情況下數(shù)據(jù)庫壓力劇增,使得響應(yīng)速度變慢。但是在使用消息隊(duì)列之后,用戶的請(qǐng)求數(shù)據(jù)發(fā)送給消息隊(duì)列之后立即 返回,再由消息隊(duì)列的消費(fèi)者進(jìn)程從消息隊(duì)列中獲取數(shù)據(jù),異步寫入數(shù)據(jù)庫。由于消息隊(duì)列服務(wù)器處理速度快于數(shù)據(jù)庫(消息隊(duì)列也比數(shù)據(jù)庫有更好的伸縮性),因此響應(yīng)速度得到大幅改善。

通過以上分析我們可以得出消息隊(duì)列具有很好的削峰作用的功能——即通過異步處理,將短時(shí)間高并發(fā)產(chǎn)生的事務(wù)消息存儲(chǔ)在消息隊(duì)列中,從而削平高峰期的并發(fā)事務(wù)。 舉例:在電子商務(wù)一些秒殺、促銷活動(dòng)中,合理使用消息隊(duì)列可以有效抵御促銷活動(dòng)剛開始大量訂單涌入對(duì)系統(tǒng)的沖擊。如下圖所示:

因?yàn)?strong>用戶請(qǐng)求數(shù)據(jù)寫入消息隊(duì)列之后就立即返回給用戶了,但是請(qǐng)求數(shù)據(jù)在后續(xù)的業(yè)務(wù)校驗(yàn)、寫數(shù)據(jù)庫等操作中可能失敗。因此使用消息隊(duì)列進(jìn)行異步處理之后,需要適當(dāng)修改業(yè)務(wù)流程進(jìn)行配合,比如用戶在提交訂單之后,訂單數(shù)據(jù)寫入消息隊(duì)列,不能立即返回用戶訂單提交成功,需要在消息隊(duì)列的訂單消費(fèi)者進(jìn)程真正處理完該訂單之后,甚至出庫后,再通過電子郵件或短信通知用戶訂單成功,以免交易糾紛。這就類似我們平時(shí)手機(jī)訂火車票和電影票。

②.降低系統(tǒng)耦合性

我們知道模塊分布式部署以后聚合方式通常有兩種:1.分布式消息隊(duì)列和2.分布式服務(wù)

先來簡單說一下分布式服務(wù):

目前使用比較多的用來構(gòu)建SOA(Service Oriented Architecture面向服務(wù)體系結(jié)構(gòu))分布式服務(wù)框架是阿里巴巴開源的Dubbo.如果想深入了解Dubbo的可以看我寫的關(guān)于Dubbo的這一篇文章:《高性能優(yōu)秀的服務(wù)框架-dubbo介紹》:https://juejin.im/post/5acadeb1f265da2375072f9c

再來談我們的分布式消息隊(duì)列:

我們知道如果模塊之間不存在直接調(diào)用,那么新增模塊或者修改模塊就對(duì)其他模塊影響較小,這樣系統(tǒng)的可擴(kuò)展性無疑更好一些。

我們最常見的事件驅(qū)動(dòng)架構(gòu)類似生產(chǎn)者消費(fèi)者模式,在大型網(wǎng)站中通常用利用消息隊(duì)列實(shí)現(xiàn)事件驅(qū)動(dòng)結(jié)構(gòu)。如下圖所示:

消息隊(duì)列使利用發(fā)布-訂閱模式工作,消息發(fā)送者(生產(chǎn)者)發(fā)布消息,一個(gè)或多個(gè)消息接受者(消費(fèi)者)訂閱消息。 從上圖可以看到消息發(fā)送者(生產(chǎn)者)和消息接受者(消費(fèi)者)之間沒有直接耦合,消息發(fā)送者將消息發(fā)送至分布式消息隊(duì)列即結(jié)束對(duì)消息的處理,消息接受者從分布式消息隊(duì)列獲取該消息后進(jìn)行后續(xù)處理,并不需要知道該消息從何而來。對(duì)新增業(yè)務(wù),只要對(duì)該類消息感興趣,即可訂閱該消息,對(duì)原有系統(tǒng)和業(yè)務(wù)沒有任何影響,從而實(shí)現(xiàn)網(wǎng)站業(yè)務(wù)的可擴(kuò)展性設(shè)計(jì)。

消息接受者對(duì)消息進(jìn)行過濾、處理、包裝后,構(gòu)造成一個(gè)新的消息類型,將消息繼續(xù)發(fā)送出去,等待其他消息接受者訂閱該消息。因此基于事件(消息對(duì)象)驅(qū)動(dòng)的業(yè)務(wù)架構(gòu)可以是一系列流程。

另外為了避免消息隊(duì)列服務(wù)器宕機(jī)造成消息丟失,會(huì)將成功發(fā)送到消息隊(duì)列的消息存儲(chǔ)在消息生產(chǎn)者服務(wù)器上,等消息真正被消費(fèi)者服務(wù)器處理后才刪除消息。在消息隊(duì)列服務(wù)器宕機(jī)后,生產(chǎn)者服務(wù)器會(huì)選擇分布式消息隊(duì)列服務(wù)器集群中的其他服務(wù)器發(fā)布消息。

備注: 不要認(rèn)為消息隊(duì)列只能利用發(fā)布-訂閱模式工作,只不過在解耦這個(gè)特定業(yè)務(wù)環(huán)境下是使用發(fā)布-訂閱模式的,比如在我們的ActiveMQ消息隊(duì)列中還有點(diǎn)對(duì)點(diǎn)工作模式,具體的會(huì)在后面的文章給大家詳細(xì)介紹,這一篇文章主要還是讓大家對(duì)消息隊(duì)列有一個(gè)更透徹的了解。

這個(gè)問題一般會(huì)在上一個(gè)問題問完之后,緊接著被問到?!笆褂孟㈥?duì)列會(huì)帶來什么問題?”這個(gè)問題要引起重視,一般我們都會(huì)考慮使用消息隊(duì)列會(huì)帶來的好處而忽略它帶來的問題!
1.2 那么使用消息隊(duì)列會(huì)帶來什么問題?考慮過這個(gè)問題嗎?

系統(tǒng)可用性降低:系統(tǒng)可用性在某種程度上降低,為什么這樣說呢?在加入MQ之前,你不用考慮消息丟失或者說MQ掛掉等等的情況,但是,引入MQ之后你就需要去考慮了!

系統(tǒng)復(fù)雜性提高: 加入MQ之后,你需要保證消息沒有被重復(fù)消費(fèi)、處理消息丟失的情況、保證消息傳遞的順序性等等問題!

一致性問題: 我上面講了消息隊(duì)列可以實(shí)現(xiàn)異步,消息隊(duì)列帶來的異步確實(shí)可以提高系統(tǒng)響應(yīng)速度。但是,萬一消息的真正消費(fèi)者并沒有正確消費(fèi)消息怎么辦?這樣就會(huì)導(dǎo)致數(shù)據(jù)不一致的情況了!

了解下面這個(gè)問題是為了我們更好的進(jìn)行技術(shù)選型!該部分摘自:《Java工程師面試突擊第1季-中華石杉老師》,如果大家沒有資源的話,可以在我的公眾號(hào)“Java面試通關(guān)手冊(cè)”后臺(tái)回復(fù)關(guān)鍵字“1”即可!
1.3 介紹一下你知道哪幾種消息隊(duì)列,該如何選擇呢?
特性 ActiveMQ RabbitMQ RocketMQ Kafaka
單機(jī)吞吐量 萬級(jí),吞吐量比RocketMQ和Kafka要低了一個(gè)數(shù)量級(jí) 萬級(jí),吞吐量比RocketMQ和Kafka要低了一個(gè)數(shù)量級(jí) 10萬級(jí),RocketMQ也是可以支撐高吞吐的一種MQ 10萬級(jí)別,這是kafka最大的優(yōu)點(diǎn),就是吞吐量高。一般配合大數(shù)據(jù)類的系統(tǒng)來進(jìn)行實(shí)時(shí)數(shù)據(jù)計(jì)算、日志采集等場(chǎng)景
topic數(shù)量對(duì)吞吐量的影響 topic可以達(dá)到幾百,幾千個(gè)的級(jí)別,吞吐量會(huì)有較小幅度的下降這是RocketMQ的一大優(yōu)勢(shì),在同等機(jī)器下,可以支撐大量的topic topic從幾十個(gè)到幾百個(gè)的時(shí)候,吞吐量會(huì)大幅度下降。所以在同等機(jī)器下,kafka盡量保證topic數(shù)量不要過多。如果要支撐大規(guī)模topic,需要增加更多的機(jī)器資源
可用性 高,基于主從架構(gòu)實(shí)現(xiàn)高可用性 高,基于主從架構(gòu)實(shí)現(xiàn)高可用性 非常高,分布式架構(gòu) 非常高,kafka是分布式的,一個(gè)數(shù)據(jù)多個(gè)副本,少數(shù)機(jī)器宕機(jī),不會(huì)丟失數(shù)據(jù),不會(huì)導(dǎo)致不可用
消息可靠性 有較低的概率丟失數(shù)據(jù) 經(jīng)過參數(shù)優(yōu)化配置,可以做到0丟失 經(jīng)過參數(shù)優(yōu)化配置,消息可以做到0丟失
時(shí)效性 ms級(jí) 微秒級(jí),這是rabbitmq的一大特點(diǎn),延遲是最低的 ms級(jí) 延遲在ms級(jí)以內(nèi)
功能支持 MQ領(lǐng)域的功能極其完備 基于erlang開發(fā),所以并發(fā)能力很強(qiáng),性能極其好,延時(shí)很低 MQ功能較為完善,還是分布式的,擴(kuò)展性好 功能較為簡單,主要支持簡單的MQ功能,在大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算以及日志采集被大規(guī)模使用,是事實(shí)上的標(biāo)準(zhǔn)
優(yōu)劣勢(shì)總結(jié) 非常成熟,功能強(qiáng)大,在業(yè)內(nèi)大量的公司以及項(xiàng)目中都有應(yīng)用。偶爾會(huì)有較低概率丟失消息,而且現(xiàn)在社區(qū)以及國內(nèi)應(yīng)用都越來越少,官方社區(qū)現(xiàn)在對(duì)ActiveMQ 5.x維護(hù)越來越少,幾個(gè)月才發(fā)布一個(gè)版本而且確實(shí)主要是基于解耦和異步來用的,較少在大規(guī)模吞吐的場(chǎng)景中使用 erlang語言開發(fā),性能極其好,延時(shí)很低;吞吐量到萬級(jí),MQ功能比較完備而且開源提供的管理界面非常棒,用起來很好用。社區(qū)相對(duì)比較活躍,幾乎每個(gè)月都發(fā)布幾個(gè)版本分在國內(nèi)一些互聯(lián)網(wǎng)公司近幾年用rabbitmq也比較多一些但是問題也是顯而易見的,RabbitMQ確實(shí)吞吐量會(huì)低一些,這是因?yàn)樗龅膶?shí)現(xiàn)機(jī)制比較重。而且erlang開發(fā),國內(nèi)有幾個(gè)公司有實(shí)力做erlang源碼級(jí)別的研究和定制?如果說你沒這個(gè)實(shí)力的話,確實(shí)偶爾會(huì)有一些問題,你很難去看懂源碼,你公司對(duì)這個(gè)東西的掌控很弱,基本職能依賴于開源社區(qū)的快速維護(hù)和修復(fù)bug。而且rabbitmq集群動(dòng)態(tài)擴(kuò)展會(huì)很麻煩,不過這個(gè)我覺得還好。其實(shí)主要是erlang語言本身帶來的問題。很難讀源碼,很難定制和掌控。 接口簡單易用,而且畢竟在阿里大規(guī)模應(yīng)用過,有阿里品牌保障。日處理消息上百億之多,可以做到大規(guī)模吞吐,性能也非常好,分布式擴(kuò)展也很方便,社區(qū)維護(hù)還可以,可靠性和可用性都是ok的,還可以支撐大規(guī)模的topic數(shù)量,支持復(fù)雜MQ業(yè)務(wù)場(chǎng)景。而且一個(gè)很大的優(yōu)勢(shì)在于,阿里出品都是java系的,我們可以自己閱讀源碼,定制自己公司的MQ,可以掌控。社區(qū)活躍度相對(duì)較為一般,不過也還可以,文檔相對(duì)來說簡單一些,然后接口這塊不是按照標(biāo)準(zhǔn)JMS規(guī)范走的有些系統(tǒng)要遷移需要修改大量代碼。還有就是阿里出臺(tái)的技術(shù),你得做好這個(gè)技術(shù)萬一被拋棄,社區(qū)黃掉的風(fēng)險(xiǎn),那如果你們公司有技術(shù)實(shí)力我覺得用RocketMQ挺好的 kafka的特點(diǎn)其實(shí)很明顯,就是僅僅提供較少的核心功能,但是提供超高的吞吐量,ms級(jí)的延遲,極高的可用性以及可靠性,而且分布式可以任意擴(kuò)展。同時(shí)kafka最好是支撐較少的topic數(shù)量即可,保證其超高吞吐量。而且kafka唯一的一點(diǎn)劣勢(shì)是有可能消息重復(fù)消費(fèi),那么對(duì)數(shù)據(jù)準(zhǔn)確性會(huì)造成極其輕微的影響,在大數(shù)據(jù)領(lǐng)域中以及日志采集中,這點(diǎn)輕微影響可以忽略這個(gè)特性天然適合大數(shù)據(jù)實(shí)時(shí)計(jì)算以及日志收集。
這部分內(nèi)容,我這里不給出答案,大家可以自行根據(jù)自己學(xué)習(xí)的消息隊(duì)列查閱相關(guān)內(nèi)容,我可能會(huì)在后面的文章中介紹到這部分內(nèi)容。另外,下面這些問題在視頻《Java工程師面試突擊第1季-中華石杉老師》中都有提到,如果大家沒有資源的話,可以在我的公眾號(hào)“Java面試通關(guān)手冊(cè)”后臺(tái)回復(fù)關(guān)鍵字“1”即可!
1.4 關(guān)于消息隊(duì)列其他一些常見的問題展望

引入消息隊(duì)列之后如何保證高可用性

如何保證消息不被重復(fù)消費(fèi)呢?

如何保證消息的可靠性傳輸(如何處理消息丟失的問題)?

我該怎么保證從消息隊(duì)列里拿到的數(shù)據(jù)按順序執(zhí)行?

如何解決消息隊(duì)列的延時(shí)以及過期失效問題?消息隊(duì)列滿了以后該怎么處理?有幾百萬消息持續(xù)積壓幾小時(shí),說說怎么解決?

如果讓你來開發(fā)一個(gè)消息隊(duì)列中間件,你會(huì)怎么設(shè)計(jì)架構(gòu)?

二 談?wù)?InnoDB 和 MyIsam 兩者的區(qū)別 2.1 兩者的對(duì)比

1) count運(yùn)算上的區(qū)別: 因?yàn)镸yISAM緩存有表meta-data(行數(shù)等),因此在做COUNT(*)時(shí)對(duì)于一個(gè)結(jié)構(gòu)很好的查詢是不需要消耗多少資源的。而對(duì)于InnoDB來說,則沒有這種緩存。

2) 是否支持事務(wù)和崩潰后的安全恢復(fù): MyISAM 強(qiáng)調(diào)的是性能,每次查詢具有原子性,其執(zhí)行數(shù)度比InnoDB類型更快,但是不提供事務(wù)支持。但是InnoDB 提供事務(wù)支持事務(wù),外部鍵等高級(jí)數(shù)據(jù)庫功能。 具有事務(wù)(commit)、回滾(rollback)和崩潰修復(fù)能力(crash recovery capabilities)的事務(wù)安全(transaction-safe (ACID compliant))型表。

3)是否支持外鍵: MyISAM不支持,而InnoDB支持。

2.2 關(guān)于兩者的總結(jié)

MyISAM更適合讀密集的表,而InnoDB更適合寫密集的的表。 在數(shù)據(jù)庫做主從分離的情況下,經(jīng)常選擇MyISAM作為主庫的存儲(chǔ)引擎。

一般來說,如果需要事務(wù)支持,并且有較高的并發(fā)讀取頻率(MyISAM的表鎖的粒度太大,所以當(dāng)該表寫并發(fā)量較高時(shí),要等待的查詢就會(huì)很多了),InnoDB是不錯(cuò)的選擇。如果你的數(shù)據(jù)量很大(MyISAM支持壓縮特性可以減少磁盤的空間占用),而且不需要支持事務(wù)時(shí),MyISAM是最好的選擇。

三 聊聊 Java 中的集合吧! 3.1 Arraylist 與 LinkedList 有什么不同?(注意加上從數(shù)據(jù)結(jié)構(gòu)分析的內(nèi)容)

1. 是否保證線程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保證線程安全;

2. 底層數(shù)據(jù)結(jié)構(gòu): Arraylist 底層使用的是Object數(shù)組;LinkedList 底層使用的是雙向鏈表數(shù)據(jù)結(jié)構(gòu)(注意雙向鏈表和雙向循環(huán)鏈表的區(qū)別:);

3. 插入和刪除是否受元素位置的影響:ArrayList 采用數(shù)組存儲(chǔ),所以插入和刪除元素的時(shí)間復(fù)雜度受元素位置的影響。 比如:執(zhí)行add(E e) 方法的時(shí)候, ArrayList 會(huì)默認(rèn)在將指定的元素追加到此列表的末尾,這種情況時(shí)間復(fù)雜度就是O(1)。但是如果要在指定位置 i 插入和刪除元素的話(add(int index, E element) )時(shí)間復(fù)雜度就為 O(n-i)。因?yàn)樵谶M(jìn)行上述操作的時(shí)候集合中第 i 和第 i 個(gè)元素之后的(n-i)個(gè)元素都要執(zhí)行向后位/向前移一位的操作。 ② LinkedList 采用鏈表存儲(chǔ),所以插入,刪除元素時(shí)間復(fù)雜度不受元素位置的影響,都是近似 O(1)而數(shù)組為近似 O(n)。

4. 是否支持快速隨機(jī)訪問: LinkedList 不支持高效的隨機(jī)元素訪問,而 ArrayList 支持??焖匐S機(jī)訪問就是通過元素的序號(hào)快速獲取元素對(duì)象(對(duì)應(yīng)于get(int index) 方法)。

5. 內(nèi)存空間占用: ArrayList的空 間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾會(huì)預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗比ArrayList更多的空間(因?yàn)橐娣胖苯雍罄^和直接前驅(qū)以及數(shù)據(jù))。

補(bǔ)充內(nèi)容:RandomAccess接口

public interface RandomAccess {
}

查看源碼我們發(fā)現(xiàn)實(shí)際上 RandomAccess 接口中什么都沒有定義。所以,在我看來 RandomAccess 接口不過是一個(gè)標(biāo)識(shí)罷了。標(biāo)識(shí)什么? 標(biāo)識(shí)實(shí)現(xiàn)這個(gè)接口的類具有隨機(jī)訪問功能。

在binarySearch()方法中,它要判斷傳入的list 是否RamdomAccess的實(shí)例,如果是,調(diào)用indexedBinarySearch()方法,如果不是,那么調(diào)用iteratorBinarySearch()方法

    public static 
    int binarySearch(List> list, T key) {
        if (list instanceof RandomAccess || list.size()

ArraysList 實(shí)現(xiàn)了 RandomAccess 接口, 而 LinkedList 沒有實(shí)現(xiàn)。為什么呢?我覺得還是和底層數(shù)據(jù)結(jié)構(gòu)有關(guān)!ArraysList 底層是數(shù)組,而 LinkedList 底層是鏈表。數(shù)組天然支持隨機(jī)訪問,時(shí)間復(fù)雜度為 O(1),所以稱為快速隨機(jī)訪問。鏈表需要遍歷到特定位置才能訪問特定位置的元素,時(shí)間復(fù)雜度為 O(n),所以不支持快速隨機(jī)訪問。,ArraysList 實(shí)現(xiàn)了 RandomAccess 接口,就表明了他具有快速隨機(jī)訪問功能。 RandomAccess 接口只是標(biāo)識(shí),并不是說 ArraysList 實(shí)現(xiàn) RandomAccess 接口才具有快速隨機(jī)訪問功能的!

下面再總結(jié)一下 list 的遍歷方式選擇:

實(shí)現(xiàn)了RadmoAcces接口的list,優(yōu)先選擇普通for循環(huán) ,其次foreach,

未實(shí)現(xiàn)RadmoAcces接口的ist, 優(yōu)先選擇iterator遍歷(foreach遍歷底層也是通過iterator實(shí)現(xiàn)的),大size的數(shù)據(jù),千萬不要使用普通for循環(huán)

Java 中的集合這類問題幾乎是面試必問的,問到這類問題的時(shí)候,HashMap 又是幾乎必問的問題,所以大家一定要引起重視!
3.2 HashMap的底層實(shí)現(xiàn) ① JDK1.8之前

JDK1.8 之前 HashMap 底層是 數(shù)組和鏈表 結(jié)合在一起使用也就是 鏈表散列HashMap 通過 key 的 hashCode 經(jīng)過擾動(dòng)函數(shù)處理過后得到 hash 值,然后通過 (n - 1) & hash 判斷當(dāng)前元素存放的位置(這里的 n 指的時(shí)數(shù)組的長度),如果當(dāng)前位置存在元素的話,就判斷該元素與要存入的元素的 hash 值以及 key 是否相同,如果相同的話,直接覆蓋,不相同就通過拉鏈法解決沖突。

所謂擾動(dòng)函數(shù)指的就是 HashMap 的 hash 方法。使用 hash 方法也就是擾動(dòng)函數(shù)是為了防止一些實(shí)現(xiàn)比較差的 hashCode() 方法 換句話說使用擾動(dòng)函數(shù)之后可以減少碰撞。

JDK 1.8 HashMap 的 hash 方法源碼:

JDK 1.8 的 hash方法 相比于 JDK 1.7 hash 方法更加簡化,但是原理不變。

      static final int hash(Object key) {
        int h;
        // key.hashCode():返回散列值也就是hashcode
        // ^ :按位異或
        // >>>:無符號(hào)右移,忽略符號(hào)位,空位都以0補(bǔ)齊
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

對(duì)比一下 JDK1.7的 HashMap 的 hash 方法源碼.

static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).

    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

相比于 JDK1.8 的 hash 方法 ,JDK 1.7 的 hash 方法的性能會(huì)稍差一點(diǎn)點(diǎn),因?yàn)楫吘箶_動(dòng)了 4 次。

所謂 “拉鏈法” 就是:將鏈表和數(shù)組相結(jié)合。也就是說創(chuàng)建一個(gè)鏈表數(shù)組,數(shù)組中每一格就是一個(gè)鏈表。若遇到哈希沖突,則將沖突的值加到鏈表中即可。

② JDK1.8之后

相比于之前的版本, JDK1.8之后在解決哈希沖突時(shí)有了較大的變化,當(dāng)鏈表長度大于閾值(默認(rèn)為8)時(shí),將鏈表轉(zhuǎn)化為紅黑樹,以減少搜索時(shí)間。

TreeMap、TreeSet以及JDK1.8之后的HashMap底層都用到了紅黑樹。紅黑樹就是為了解決二叉查找樹的缺陷,因?yàn)槎娌檎覙湓谀承┣闆r下會(huì)退化成一個(gè)線性結(jié)構(gòu)。

問完 HashMap 的底層原理之后,面試官可能就會(huì)緊接著問你 HashMap 底層數(shù)據(jù)結(jié)構(gòu)相關(guān)的問題!
3.3 既然談到了紅黑樹,你給我手繪一個(gè)出來吧,然后簡單講一下自己對(duì)于紅黑樹的理解

紅黑樹特點(diǎn):

每個(gè)節(jié)點(diǎn)非紅即黑;

根節(jié)點(diǎn)總是黑色的;

每個(gè)葉子節(jié)點(diǎn)都是黑色的空節(jié)點(diǎn)(NIL節(jié)點(diǎn));

如果節(jié)點(diǎn)是紅色的,則它的子節(jié)點(diǎn)必須是黑色的(反之不一定);

從根節(jié)點(diǎn)到葉節(jié)點(diǎn)或空子節(jié)點(diǎn)的每條路徑,必須包含相同數(shù)目的黑色節(jié)點(diǎn)(即相同的黑色高度)

紅黑樹的應(yīng)用:

TreeMap、TreeSet以及JDK1.8之后的HashMap底層都用到了紅黑樹。

為什么要用紅黑樹

簡單來說紅黑樹就是為了解決二叉查找樹的缺陷,因?yàn)槎娌檎覙湓谀承┣闆r下會(huì)退化成一個(gè)線性結(jié)構(gòu)。

3.4 紅黑樹這么優(yōu)秀,為何不直接使用紅黑樹得了?

說一下自己對(duì)于這個(gè)問題的看法:我們知道紅黑樹屬于(自)平衡二叉樹,但是為了保持“平衡”是需要付出代價(jià)的,紅黑樹在插入新數(shù)據(jù)后可能需要通過左旋,右旋、變色這些操作來保持平衡,這費(fèi)事啊。你說說我們引入紅黑樹就是為了查找數(shù)據(jù)快,如果鏈表長度很短的話,根本不需要引入紅黑樹的,你引入之后還要付出代價(jià)維持它的平衡。但是鏈表過長就不一樣了。至于為什么選 8 這個(gè)值呢?通過概率統(tǒng)計(jì)所得,這個(gè)值是綜合查詢成本和新增元素成本得出的最好的一個(gè)值。

3.5 HashMap 和 Hashtable 的區(qū)別/HashSet 和 HashMap 區(qū)別

HashMap 和 Hashtable 的區(qū)別

線程是否安全: HashMap 是非線程安全的,HashTable 是線程安全的;HashTable 內(nèi)部的方法基本都經(jīng)過 synchronized 修飾。(如果你要保證線程安全的話就使用 ConcurrentHashMap 吧?。?/p>

效率: 因?yàn)榫€程安全的問題,HashMap 要比 HashTable 效率高一點(diǎn)。另外,HashTable 基本被淘汰,不要在代碼中使用它;

對(duì)Null key 和Null value的支持: HashMap 中,null 可以作為鍵,這樣的鍵只有一個(gè),可以有一個(gè)或多個(gè)鍵所對(duì)應(yīng)的值為 null。。但是在 HashTable 中 put 進(jìn)的鍵值只要有一個(gè) null,直接拋出 NullPointerException。

初始容量大小和每次擴(kuò)充容量大小的不同 : ①創(chuàng)建時(shí)如果不指定容量初始值,Hashtable 默認(rèn)的初始大小為11,之后每次擴(kuò)充,容量變?yōu)樵瓉淼?n+1。HashMap 默認(rèn)的初始化大小為16。之后每次擴(kuò)充,容量變?yōu)樵瓉淼?倍。②創(chuàng)建時(shí)如果給定了容量初始值,那么 Hashtable 會(huì)直接使用你給定的大小,而 HashMap 會(huì)將其擴(kuò)充為2的冪次方大小(HashMap 中的tableSizeFor()方法保證,下面給出了源代碼)。也就是說 HashMap 總是使用2的冪作為哈希表的大小,后面會(huì)介紹到為什么是2的冪次方。

底層數(shù)據(jù)結(jié)構(gòu): JDK1.8 以后的 HashMap 在解決哈希沖突時(shí)有了較大的變化,當(dāng)鏈表長度大于閾值(默認(rèn)為8)時(shí),將鏈表轉(zhuǎn)化為紅黑樹,以減少搜索時(shí)間。Hashtable 沒有這樣的機(jī)制。

HashSet 和 HashMap 區(qū)別

如果你看過 HashSet 源碼的話就應(yīng)該知道:HashSet 底層就是基于 HashMap 實(shí)現(xiàn)的。(HashSet 的源碼非常非常少,因?yàn)槌?clone() 方法、writeObject()方法、readObject()方法是 HashSet 自己不得不實(shí)現(xiàn)之外,其他方法都是直接調(diào)用 HashMap 中的方法。)

你若盛開,清風(fēng)自來。 歡迎關(guān)注我的微信公眾號(hào):“Java面試通關(guān)手冊(cè)”,一個(gè)有溫度的微信公眾號(hào)。公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字“1”,可以免費(fèi)獲取一份我精心準(zhǔn)備的小禮物哦!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/72172.html

相關(guān)文章

  • 備戰(zhàn)春招/秋招系列美團(tuán)面經(jīng)總結(jié)基礎(chǔ)詳解答案

    摘要:不同于個(gè)人面經(jīng),這份面經(jīng)具有普適性。我在前面的文章中也提到了應(yīng)該怎么做自我介紹與項(xiàng)目介紹,詳情可以查看這篇文章備戰(zhàn)春招秋招系列初出茅廬的程序員該如何準(zhǔn)備面試。是建立連接時(shí)使用的握手信號(hào)。它表示確認(rèn)發(fā)來的數(shù)據(jù)已經(jīng)接受無誤。 showImg(https://segmentfault.com/img/remote/1460000016972448?w=921&h=532); 該文已加入開源文...

    Leck1e 評(píng)論0 收藏0
  • 前端最強(qiáng)面經(jīng)匯總

    摘要:獲取的對(duì)象范圍方法獲取的是最終應(yīng)用在元素上的所有屬性對(duì)象即使沒有代碼,也會(huì)把默認(rèn)的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對(duì)于一個(gè)光禿禿的元素,方法返回對(duì)象中屬性值如果有就是據(jù)我測(cè)試不同環(huán)境結(jié)果可能有差異而就是。 花了很長時(shí)間整理的前端面試資源,喜歡請(qǐng)大家不要吝嗇star~ 別只收藏,點(diǎn)個(gè)贊,點(diǎn)個(gè)star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項(xiàng)目地址 https:...

    wangjuntytl 評(píng)論0 收藏0
  • "雙非"應(yīng)屆生校招如何獲得大廠青睞?(內(nèi)前端大廠面經(jīng)+技術(shù)崗超全求職攻略)

    摘要:拿到秋招的同學(xué),如確定入職需與用人單位簽署三方協(xié)議,以保證雙方的利益不受損失。當(dāng)然每個(gè)崗位所要求的側(cè)重點(diǎn)不同,但卻百變不離其宗。方法論要想達(dá)成某個(gè)目標(biāo)都有其特定的方法論,學(xué)習(xí)技術(shù)也不例外,掌握適當(dāng)?shù)膶W(xué)習(xí)方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準(zhǔn)備春招,其中遇到不少坑,也意識(shí)到自己走過的彎路。故寫了這篇文章總結(jié)一番,本文適合主動(dòng)學(xué)習(xí)的,對(duì)自己要學(xué)的課程不明確的,對(duì)面試有...

    jeffrey_up 評(píng)論0 收藏0
  • "雙非"應(yīng)屆生校招如何獲得大廠青睞?(內(nèi)前端大廠面經(jīng)+技術(shù)崗超全求職攻略)

    摘要:拿到秋招的同學(xué),如確定入職需與用人單位簽署三方協(xié)議,以保證雙方的利益不受損失。當(dāng)然每個(gè)崗位所要求的側(cè)重點(diǎn)不同,但卻百變不離其宗。方法論要想達(dá)成某個(gè)目標(biāo)都有其特定的方法論,學(xué)習(xí)技術(shù)也不例外,掌握適當(dāng)?shù)膶W(xué)習(xí)方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準(zhǔn)備春招,其中遇到不少坑,也意識(shí)到自己走過的彎路。故寫了這篇文章總結(jié)一番,本文適合主動(dòng)學(xué)習(xí)的,對(duì)自己要學(xué)的課程不明確的,對(duì)面試有...

    lindroid 評(píng)論0 收藏0
  • 備戰(zhàn)春招/秋招系列Java程序員必備書單

    摘要:相關(guān)推薦,豆瓣評(píng)分,人評(píng)價(jià)本書介紹了在編程中條極具實(shí)用價(jià)值的經(jīng)驗(yàn)規(guī)則,這些經(jīng)驗(yàn)規(guī)則涵蓋了大多數(shù)開發(fā)人員每天所面臨的問題的解決方案。實(shí)戰(zhàn)高并發(fā)程序設(shè)計(jì)推薦豆瓣評(píng)分,書的質(zhì)量沒的說,推薦大家好好看一下。 該文已加入開源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識(shí))。地址:https://github.com/Snailclimb... 【強(qiáng)烈推薦!非廣告!】...

    saucxs 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<