java中有幾種經常使用的數據結構,主要分爲Collection和map兩個主要接口(接口只提供方法,並不提供實現),而程序中最終使用的數據結構是繼承自這些接口的數據結構類。 html
public interface Collection<E> extends Iterable<E> {}
它是一個接口,是高度抽象出來的集合,它包含了集合的基本操做:添加、刪除、清空、遍歷(讀取)、是否爲空、獲取大小、是否保護某元素等等。java
Collection接口的全部子類(直接子類和間接子類)都必須實現2種構造函數:不帶參數的構造函數 和 參數爲Collection的構造函數。帶參數的構造函數,能夠用來轉換Collection的類型。算法
public interface List<E> extends Collection<E> {}
二、List接口的實現類數據庫
(1)ArrayList:底層數據結構是數組,查詢快,增刪慢,線程不安全,效率高,能夠存儲重複元素
(2)LinkedList 底層數據結構是鏈表,查詢慢,增刪快,線程不安全,效率高,能夠存儲重複元素
(3)Vector:底層數據結構是數組,查詢快,增刪慢,線程安全,效率低,能夠存儲重複元素 數組
三、List接口的方法:既然List是繼承於Collection接口,它天然就包含了Collection中的所有函數接口;因爲List是有序隊列,它也額外的有本身的API接口。安全
Arraylist:
優勢:ArrayList是實現了基於動態數組的數據結構,由於地址連續,一旦數據存儲好了,查詢操做效率會比較高(在內存裏是連着放的)。
缺點:由於地址連續, ArrayList要移動數據,因此插入和刪除操做效率比較低。數據結構
LinkedList:
優勢:LinkedList基於鏈表的數據結構,地址是任意的,因此在開闢內存空間的時候不須要等一個連續的地址,對於新增和刪除操做add和remove,LinedList比較佔優點。LinkedList 適用於要頭尾操做或插入指定位置的場景
缺點:由於LinkedList要移動指針,因此查詢操做性能比較低。
適用場景分析:
當須要對數據進行對此訪問的狀況下選用ArrayList,當須要對數據進行屢次增長刪除修改時採用LinkedList。
函數
一、定義:Set是一個繼承於Collection的接口,即Set也是集合中的一種。Set是沒有重複元素的集合。性能
public interface Set<E> extends Collection<E> {}
二、Set的API和Collection徹底同樣。spa
// Set的API abstract boolean add(E object) abstract boolean addAll(Collection<? extends E> collection) abstract void clear() abstract boolean contains(Object object) abstract boolean containsAll(Collection<?> collection) abstract boolean equals(Object object) abstract int hashCode() abstract boolean isEmpty() abstract Iterator<E> iterator() abstract boolean remove(Object object) abstract boolean removeAll(Collection<?> collection) abstract boolean retainAll(Collection<?> collection) abstract int size() abstract <T> T[] toArray(T[] array) abstract Object[] toArray()
三、實現子類
(1)HashSet : 底層數據結構採用哈希表實現,元素無序且惟一,線程不安全,效率高,能夠存儲null元素,元素的惟一性是靠所存儲元素類型是否重寫hashCode()和equals()方法來保證的,若是沒有重寫這兩個方法,則沒法保證元素的惟一性。
a、實現惟一性:
存儲元素首先會使用hash()算法函數生成一個int類型hashCode散列值,而後已經的所存儲的元素的hashCode值比較,若是hashCode不相等,則所存儲的兩個對象必定不相等,此時存儲當前的新的hashCode值處的元素對象;若是hashCode相等,存儲元素的對象仍是不必定相等,此時會調用equals()方法判斷兩個對象的內容是否相等,若是內容相等,那麼就是同一個對象,無需存儲;若是比較的內容不相等,那麼就是不一樣的對象,就該存儲了,此時就要採用哈希的解決地址衝突算法,在當前hashCode值處相似一個新的鏈表, 在同一個hashCode值的後面存儲存儲不一樣的對象,這樣就保證了元素的惟一性。
b、實現不重複
HashSet也同樣他是使用了一種標識來肯定元素的不重複,HashSet用一種算法來保證HashSet中的元素是不重複的, HashSet採用哈希算法,底層用數組存儲數據。默認初始化容量16,加載因子0.75。
Object類中的hashCode()的方法是全部子類都會繼承這個方法,這個方法會用Hash算法算出一個Hash(哈希)碼值返回,HashSet會用Hash碼值去和數組長度取模, 模(這個模就是對象要存放在數組中的位置)相同時纔會判斷數組中的元素和要加入的對象的內容是否相同,若是不一樣纔會添加進去。
覆蓋hashCode()方法的原則:
一、必定要讓那些咱們認爲相同的對象返回相同的hashCode值
二、儘可能讓那些咱們認爲不一樣的對象返回不一樣的hashCode值,不然,就會增長衝突的機率。
三、儘可能的讓hashCode值散列開(兩值用異或運算可以使結果的範圍更廣)
c、HashSet的實現
HashSet 的實現比較簡單,相關HashSet的操做,基本上都是直接調用底層HashMap的相關方法來完成,咱們應該爲保存到HashSet中的對象覆蓋hashCode()和equals(),由於再將對象加入到HashSet中時:
首先調用hashCode方法計算出對象的hash值,接着根據此hash值調用HashMap中的hash方法,獲得的值& (length-1)獲得該對象在hashMap的transient Entry[] table中的保存位置的索引,接着找到數組中該索引位置保存的對象,並調用equals方法比較這兩個對象是否相等,若是相等則不添加;
注意:因此要存入HashSet的集合對象中的自定義類必須覆蓋hashCode(),equals()兩個方法,才能保證集合中元素不重複。在覆蓋equals()和hashCode()方法時, 要使相同對象的hashCode()方法返回相同值,覆蓋equals()方法再判斷其內容。爲了保證效率,因此在覆蓋hashCode()方法時,也要儘可能使不一樣對象儘可能返回不一樣的Hash碼值。
(2)、LinkedHashSet底層數據結構採用鏈表和哈希表共同實現,鏈表保證了元素的順序與存儲順序一致,哈希表保證了元素的惟一性。線程不安全,效率高。
(3)、TreeSet底層數據結構採用二叉樹來實現,元素惟一且已經排好序;惟一性一樣須要重寫hashCode和equals()方法,二叉樹結構保證了元素的有序性。根據構造方法不一樣,分爲天然排序(無參構造)和比較器排序(有參構造)。
天然排序要求元素必須實現Compareable接口,並重寫裏面的compareTo()方法,元素經過比較返回的int值來判斷排序序列,返回0說明兩個對象相同,不須要存儲;
比較器排鬚要在TreeSet初始化是時候傳入一個實現Comparator接口的比較器對象,或者採用匿名內部類的方式new一個Comparator對象,重寫裏面的compare()方法;
比較:
一、TreeSet 是二叉樹(紅黑樹的樹據結構)實現的,Treeset中的數據是自動排好序的,不容許放入null值;
二、HashSet 是哈希表實現的,HashSet中的數據是無序的,能夠放入null,但只能放入一個null,二者中的值都不能重複,就如數據庫中惟一約束 ;
三、HashSet要求放入的對象必須實現HashCode()方法,放入的對象,是以hashcode碼做爲標識的,而具備相同內容的String對象,hashcode是同樣,因此放入的內容不能重複。可是同一個類的對象能夠放入不一樣的實例;
適用場景分析:HashSet是基於Hash算法實現的,其性能一般都優於TreeSet。爲快速查找而設計的Set,咱們一般都應該使用HashSet,在咱們須要排序的功能時,咱們才使用TreeSet。
(1)、List,Set都是繼承自Collection接口;
(2)、List特色:元素有放入順序,元素可重複 ;Set特色:元素無放入順序,元素不可重複,重複元素會覆蓋掉;
(3)、Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引發元素位置改變。
List:和數組相似,List能夠動態增加,查找元素效率高,插入刪除元素效率低,由於會引發其餘元素位置改變。
原文:https://blog.csdn.net/feiyanaffection/article/details/81394745
http://www.cnblogs.com/skywang12345/p/3308513.html