Java面試準備-集合
問題連結轉載 Java面試通關要點彙總集【終極版】
一、List 和 Set 區別
list和set是實現了collection介面的
List
- 可以有重複項
- 有序容器,按插入的順序輸出
- 常用的實現類有ArrayList,LinkedList和Vector
Set
- 不能有重複項
- 無序容器,無法保證輸出的順序,TreeSet可以通過 Comparator 或者 Comparable 維護了一個排序順序
- 常用的實現類有HashSet,TreeSet
二、List 和 Map 區別
List實現了Collection介面,而Map沒有,它本身是一個介面。
List
- 可以有重複項
- 有序容器,按插入的順序輸出
- 常用的實現類有ArrayList,LinkedList和Vector
Map
- Map的每個Entry都有兩個物件,鍵物件和值物件。鍵物件是唯一
- Map的實現類有HashMap,TreeMap等
三、Arraylist 與 LinkedList 區別
- ArrayList是基於動態陣列的資料結構,LinkedList是基於連結串列的資料結構
- 對於隨機訪問get和set,ArrayList要快於LinkedList
- 但插入和刪除,LinkedList要優於ArrayList
四、ArrayList 與 Vector 區別
ArrayList和Vector是List的實現,Vector是執行緒安全,而ArrayList不是。因為這樣,ArrayList速度會比Vector快。當儲存空間不夠時,Vector是增長一倍,而arrayList增長50%。
五、HashMap 和 Hashtable 的區別
- HashTable是synchronized,執行緒安全,而HashMap不是執行緒安全。所以HashMap速度要快於HashTable
- Hashtable中,key和value都不允許出現null值,HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null
- Hashtable繼承自Dictionary類,而HashMap繼承自AbstractMap類。但二者都實現了Map介面
-
HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因為contains方法容易讓人引起誤解。Hashtable則保留了contains,containsValue和containsKey三個方法,其中contains和containsValue功能相同。
-
Hashtable、HashMap都使用了 Iterator。而由於歷史原因,Hashtable還使用了Enumeration的方式
-
HashTable直接使用物件的hashCode。而HashMap重新計算hash值
-
HashTable在不指定容量的情況下的預設容量為11,而HashMap為16,Hashtable不要求底層陣列的容量一定要為2的整數次冪,而HashMap則要求一定為2的整數次冪。Hashtable擴容時,將容量變為原來的2倍加1,而HashMap擴容時,將容量變為原來的2倍
六、HashSet 和 HashMap 區別
HashMap是鍵唯一,HashSet是物件唯一
*HashMap* | *HashSet* |
HashMap實現了Map介面 | HashSet實現了Set介面 |
HashMap儲存鍵值對 | HashSet僅僅儲存物件 |
使用put()方法將元素放入map中 | 使用add()方法將元素放入set中 |
HashMap中使用鍵物件來計算hashcode值 | HashSet使用成員物件來計算hashcode值,對於兩個物件來說hashcode可能相同,所以equals()方法用來判斷物件的相等性,如果兩個物件不同的話,那麼返回false |
HashMap比較快,因為是使用唯一的鍵來獲取物件 | HashSet較HashMap來說比較慢 |
七、HashMap 和 ConcurrentHashMap 的區別
在hashMap的基礎上,ConcurrentHashMap將資料分為多個segment,預設16個(concurrency level),然後每次操作對一個segment加鎖,避免多執行緒鎖得機率,提高併發效率。
八、HashMap 的工作原理及程式碼實現
HashMap基於hashing原理,我們通過put()和get()方法儲存和獲取物件。當我們將鍵值對傳遞給put()方法時,它呼叫鍵物件的hashCode()方法來計算hashcode,讓後找到bucket位置來儲存值物件。當獲取物件時,通過鍵物件的equals()方法找到正確的鍵值對,然後返回值物件。HashMap使用連結串列來解決碰撞問題,當發生碰撞了,物件將會儲存在連結串列的下一個節點中。 HashMap在每個連結串列節點中儲存鍵值對物件。
當兩個不同的鍵物件的hashcode相同時會發生什麼? 它們會儲存在同一個bucket位置的連結串列中。鍵物件的equals()方法用來找到鍵值對。
注:可以使用任何物件作為鍵,只要它遵守了equals()和hashCode()方法的定義規則
public class CustomHashMap<K, V> {
private class Entry<K, V> {
int hash;
K key;
V value;
Entry<K, V> next;
Entry(int hash, K key, V value, Entry<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
private static final int DEFAULT_CAPACITY = 1 << 4;
private Entry<K, V>[] table;
private int capacity;
private int size;
public CustomHashMap() {
this(DEFAULT_CAPACITY);
}
public CustomHashMap(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException();
} else {
table = new Entry[capacity];
size = 0;
this.capacity = capacity;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0 ? true : false;
}
private int hash(K key) {
double tmp = key.hashCode() * (Math.pow(5, 0.5) - 1) / 2;
double digit = tmp - Math.floor(tmp);
return (int) Math.floor(digit * capacity);
}
public void put(K key, V value) {
if (key == null) {
throw new IllegalArgumentException();
}
int hash = hash(key);
Entry<K, V> nEntry = new Entry<K, V>(hash, key, value, null);
Entry<K, V> entry = table[hash];
while (entry != null) {
if (entry.key.equals(key)) {
entry.value = value;
return;
}
entry = entry.next;
}
nEntry.next = table[hash];
table[hash] = nEntry;
size++;
}
public V get(K key) {
if (key == null) {
throw new IllegalArgumentException();
}
int hash = hash(key);
Entry<K, V> entry = table[hash];
while (entry != null) {
if (entry.key.equals(key)) {
return entry.value;
}
entry = entry.next;
}
return null;
}
public static void main(String[] args) {
CustomHashMap<String, String> map = new CustomHashMap<String, String>();
map.put("1", "11");
map.put("1", "22");
map.put("3", "33");
System.out.println(map.get("1"));
}
}
九、ConcurrentHashMap 的工作原理及程式碼實現
ConcurrentHashMap採用的是鎖分段技術,內部為Segment陣列來進行細分,而每個Segment又通過HashEntry陣列來進行組裝,當進行寫操作的時候,只需要對這個key對應的Segment進行加鎖操作,加鎖同時不會對其他的Segment造成影響。總的Map包含了16個Segment(預設數量),每個Segment內部包含16個HashEntry(預設數量),這樣對於這個key所在的Segment加鎖的同時,其他15個Segmeng還能正常使用,在效能上有了大大的提升。