1. 程式人生 > >Java面試準備-集合

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還能正常使用,在效能上有了大大的提升。