就在昨天,有幸接到了阿里的面試通知,原本我覺得本身的簡歷應該不會的到面試的機會了,然而機會卻這麼來了,我卻沒有作好準備,被面試官大大一通血虐。所以,我想寫點東西記念一下此次的經歷,也當一次教訓了。其實面試官大大問的問題我也都據說過,卻知其然不知其因此然。在這裏就整理一下了。java
本人不才,用過的也就ArrayList、LinkedList、HaseSet、HashMap這幾個。而後面試官大大就問了,ArrayList和LinkedList的區別是啥呀,我心想不就是數組和鏈表的區別嗎,本身還手寫過這玩意,就簡單說了一說,發現還真的不知道說啥,特此整理一下。
ArrayList和LinkedList的區別大體來源於內部的實現:
前者是基於可變長數組的,數組的特性就是連續存儲的,能夠方便的根據下標去查詢數據,根據下標去修改數據,而若是插入數據的話,插入到中間的話,這條數據以後的數據都須要後移,所以效率比較低,並且數組增加的時候,須要建立新的一個數組,並將數據拷貝一份,也會影響性能。
後者是基於雙向鏈表的,鏈表的特性就是不連續的,根據下標去查詢的話,須要移動鏈表的指針,必然會致使效率的下降,而數據的插入卻方便了不少,只須要修改那條數據的指針便可實現數據的插入。
除了這一個,還問了HashSet和HashTable的區別(ps:what?什麼是HashTable,沒見過呀,當時就沒答上來),後面查了一些東西才知道,HashTable就是和HashMap相似的東西,並且這玩意幾乎是面試必考的東西(ps:後悔沒有好好準備了),這裏就記錄下HashSet、HashMap以及HashTable的區別。
* HashSet:set的實現類,內部使用HashMap存放數據,數據不容許重複,這玩意就是他添加元素的實現啦面試
public boolean add(Object o) { return map.put(o, PRESENT)==null; }
* HashMap:map的一個實現類,內部的方法在默認狀況下是非同步的。HashMap能夠視爲數組和鏈表的結合體,而他的內部能夠分爲三部分:key的Set,value的Collection,Entry的Set,HashMap的存儲就是根據key的hash值找到元素的位置,統一位置的數據按鏈表的形式存儲,新加入的在鏈頭,後加入的在鏈尾。
* HashTable:繼承自Dictionary,一樣實現了Map的接口,HaseTable的方法是同步的,並且HashTable中的key和value都不容許null值。在HashMap中能夠出現一個惟一的null主鍵,所以HashMap中get()返回空時不表明不存在,須要使用containsKey()方法判斷。HashMap和HashTable都使用了iterator,同時HashTable也使用了Enumeration的方式。HashTable中直接使用了對象的hashcode,HashMap從新計算了hash值。算法
是否有序 | 是否可重複 | 線程安全性 | |
Vector | 是 | 是 | 安全(同步集合類) |
List | 是 | 是 | 不安全 |
CopyOnWriteArrayList | 是 | 是 | 讀寫分離,併發集合,數據最終一致,沒有實時一致性 |
AbstractSet | 否 | 否 | 不安全 |
HashSet | 否 | 否 | 不安全 |
TreeSet | 是(二叉樹) | 否 | 不安全 |
CopyOnWriteHashSet | 否 | 否 | 讀寫分離,併發集合,數據最終一致,沒有實時一致性 |
AbstractMap | 否 | 使用key-value來映射和存儲數據,Key必須唯一,value能夠重複 | 不安全 |
HashMap | 否 | 同上 | 不安全 |
TreeMap | 是(二叉樹) | 同上 | 不安全 |
HashTable | 否 | 同上 | 安全(同步集合類) |
ConcurrentHashMap | 否 | 同上 | 併發集合,採用可重入鎖 |
當時遇到這個問題直接蒙圈了,這東西的我通常最大值設置爲cpu線程數+1,還真的沒研究過到底怎麼設置的,說白了就是隻會拿來用,沒有深刻了解他的機制,因此面試完了,仍是回來查查資料記錄下吧。數組
簡單來講就是cpu核心數cpu利用率(1+等待時間/計算時間)。所以,若是是IO密集型的任務,就分配多一點咯,至於多少嗎,能夠本身在服務器上測下,若是懶得測,直接取極端狀況,cpu利用率100%,等待時間和計算時間一致,也就是直接取到2Ncpu左右。若是是運算密集型的話,能夠直接取等待時間爲0,也就是Ncpu。其實這只是比較懶的作法,儘可能仍是在服務器上測試下更好。安全
當聽到這個問題的時候,感受本身仍是太年輕呀,沒有深刻的去了解這些東西,只是簡單的看過,僅此而已。後悔本身沒有好好的研究這些了,因此只是簡單的回答當對象用不到的時候,由虛擬機本身負責回收。那麼問題來了,對象何時用不到,怎麼判斷用不到了呢。
這裏只是作些簡單的記錄,等有時間的時候在深刻的去研究吧,畢竟大三狗,考研黨。
gc的方法:引用計數算法、根搜索算法、標記/清除算法、複製算法、標記/整理算法服務器
這一塊我只知道一些簡單的知識,內存中的棧就是存放基本類型的變量和對象的引用變量,堆用來存放由new建立的對象和數組。深刻的知識只能查資料咯。
Java把內存分紅兩種,一種叫作棧內存,一種叫作堆內存
在函數中定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配。當在一段代碼塊中定義一個變量時,java就在棧中爲這個變量分配內存空間,當超過變量的做用域後,java會自動釋放掉爲該變量分配的內存空間,該內存空間能夠馬上被另做他用。
堆內存用於存放由new建立的對象和數組。在堆中分配的內存,由java虛擬機自動垃圾回收器來管理。在堆中產生了一個數組或者對象後,還能夠在棧中定義一個特殊的變量,這個變量的取值等於數組或者對象在堆內存中的首地址,在棧中的這個特殊的變量就變成了數組或者對象的引用變量,之後就能夠在程序中使用棧內存中的引用變量來訪問堆中的數組或者對象,引用變量至關於爲數組或者對象起的一個別名,或者代號。
引用變量是普通變量,定義時在棧中分配內存,引用變量在程序運行到做用域外釋放。而數組&對象自己在堆中分配,即便程序運行到使用new產生數組和對象的語句所在地代碼塊以外,數組和對象自己佔用的堆內存也不會被釋放,數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,可是仍然佔着內存,在隨後的一個不肯定的時間被垃圾回收器釋放掉。這個也是java比較佔內存的主要緣由,實際上,棧中的變量指向堆內存中的變量,這就是 Java 中的指針!併發