集合總結(jié)
ArrayList和LinkedList區(qū)別
ArrayList是動(dòng)態(tài)數(shù)組,而Linklist是鏈表。
ArrayList讀取快唉锌,擴(kuò)容慢。
LinkedList讀取慢竿奏,擴(kuò)容簡(jiǎn)單。
HashMap與HashTable區(qū)別
HashTable線程安全腥放,HashMap不安全泛啸;
HashMap支持null key。
集合類的繼承關(guān)系
Map跟Iterable是最頂層的接口秃症。
按照集合元素是否可以重復(fù)候址,分成set和list吕粹。
那種集合既可以作為隊(duì)列也可以作為棧?
雙端隊(duì)列deque岗仑。(double end queue)
作為隊(duì)列時(shí)匹耕,插入在第一個(gè)元素,彈出在最后一個(gè)元素荠雕。
作為棧時(shí)稳其,插入在第一個(gè)元素,彈出也在第一個(gè)元素炸卑。
hashmap的entryset是如何維護(hù)的既鞠。
使用懶加載的方法,在遍歷的時(shí)候盖文,才生成hashIteroator嘱蛋。entrySet()方法會(huì)new 一個(gè)EntrySet對(duì)象,iterator() 方法會(huì)生成一個(gè)EntryIterator對(duì)象五续,這個(gè)對(duì)象繼承與HashIterator洒敏,在構(gòu)造方法將table結(jié)構(gòu)進(jìn)行賦值。
map相關(guān)的類有那些
SortedMap
NavigableMap
TreeMap:key升序或者降序
WeakHashMap:
IdentityHashMap:key必須equal疙驾,但不能是同個(gè)對(duì)象
EnumMap:key枚舉凶伙,加hashmap
LinkedHashMap:鏈表加hashmap,順序是插入順序
HashSet與HashMap的區(qū)別
HashSet是用add方法添加元素荆萤,不重復(fù)镊靴。HashMap是用put鍵值對(duì)方法,key不重復(fù)但是value可以重復(fù)链韭。
hashMap增加元素的源碼分析
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0) //數(shù)組為空時(shí)偏竟,新建一個(gè)數(shù)組,用resize新建敞峭?
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null) //數(shù)組位置是否有值踊谋,沒值直接插入一個(gè)新節(jié)點(diǎn)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
//新插入的值跟首節(jié)點(diǎn)的hash和key都相同
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode) //紅黑樹相關(guān)的不管
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
//新插入的節(jié)點(diǎn)的hash有沖突呢,需要加在鏈表后面了
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//新插入的節(jié)點(diǎn)跟某個(gè)節(jié)點(diǎn)一樣旋讹,就更新值
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//key相同殖蚕,更新一下值
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize(); //擴(kuò)容
afterNodeInsertion(evict);
return null;
}
如何使用泛型
泛型包括:泛型類,泛型方法沉迹,泛型接口睦疫。
泛型類開頭表明泛型,函數(shù)參數(shù)可以泛型鞭呕。
泛型方法(非靜態(tài)蛤育,靜態(tài)方法只能使用方法定義的泛型)可以使用類的泛型,也可以使用方法定義的泛型。
泛型接口跟泛型類差不多瓦糕。
意義和好處:
在編譯時(shí)發(fā)現(xiàn)類型轉(zhuǎn)換錯(cuò)誤底洗。但也不是能夠完全發(fā)現(xiàn).下面就運(yùn)行時(shí)才報(bào)錯(cuò)。當(dāng)然我定義了泛型為object咕娄,等于扼殺了泛型存在的意義亥揖。
HashSet<Object> hashSet = new HashSet<>();
hashSet.add("Sting");
Iterator<Object> hehe = hashSet.iterator();
Integer rengzha = (Integer) hehe.next();
下面這種才能在編譯時(shí)報(bào)錯(cuò)。
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add("Sting");
另外圣勒,泛型不支持多態(tài)
通配符總結(jié)
限定通配符總是包括自己
上界類型通配符:add方法受限
下界類型通配符:get方法受限
如果你想從一個(gè)數(shù)據(jù)類型里獲取數(shù)據(jù)费变,使用 ? extends 通配符
如果你想把對(duì)象寫入一個(gè)數(shù)據(jù)結(jié)構(gòu)里,使用 ? super 通配符
如果你既想存灾而,又想取胡控,那就別用通配符
不能同時(shí)聲明泛型通配符上界和下界
如何在遍歷集合是修改元素
在編譯是修改元素,搞不好會(huì)出現(xiàn)Java ConcurrentModificationException問題旁趟。
解決方法是是用iterator的remove方法昼激。多線程下要加lock。
推薦使用ConcurrentHashMap或者CopyOnWriteArrayList锡搜。
參考:http://www.reibang.com/p/f3f6b12330c1
HashMap的大小為什么是2的N次冪
為了插入的值能夠盡量分散橙困。是取模來確認(rèn)位置的,hash%2的n次方耕餐。hash&(2的n次方-1)凡傅;
2的n次方-1都是1,所以數(shù)值會(huì)很分散肠缔。
ArrayMap與HashMap區(qū)別
ArrayMap消耗內(nèi)存小夏跷,但是慢。
HashMap消耗內(nèi)存大明未,但是快槽华。
linkedlist是單項(xiàng)鏈表還是雙向鏈表?
雙向的,可以查看源碼LinkedList.java
趟妥,有next和prev指針猫态。
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
java 有哪些同步的數(shù)據(jù)數(shù)據(jù)結(jié)構(gòu)?
list:
CopyOnwriteList
Vector
set:
CopyOnWriteArraySet
map:
ConcurrentHashMap
HashTable
ConcurrentModificationException怎么發(fā)生的披摄?
在遍歷集合的時(shí)候亲雪,集合數(shù)量發(fā)生變化,就會(huì)報(bào)這個(gè)錯(cuò)誤疚膊。因?yàn)榧蟽?nèi)部有一個(gè)變量modCount來記錄修改次數(shù)义辕,集合add,remove的時(shí)候這個(gè)變量就會(huì)加1,而初始化一個(gè)Iterator的時(shí)候寓盗,會(huì)記錄這個(gè)modCount终息,每次next的時(shí)候會(huì)判斷這個(gè)modCount是否有變化夺巩,如果有變化,所以在遍歷的時(shí)候周崭,這個(gè)集合修改了,因而報(bào)出ConcurrentModificationException喳张。