//先記錄一個想法……java實在是太臃腫了,純面向對象也有很多弊端……html
//能不能把java精簡一下啊!java
先上結論:算法
Array:認真看api索引的話,Array有兩個。一個是sql中的接口,一個是類,咱們在這裏說的是這個類。 sql
Arrays:對數組的一些列操做。編程
ArrayList:一個容器。api
零/概述數組
在學Java之前,一說到存放東西,第一個想到的就是使用數組,使用數組,在數據的存取方面的卻也挺方便,其存儲效率高訪問快,可是它也受到了一些限制,好比說數組的長度以及數組的類型,當我須要一組string類型數據的同時還須要Integer類型的話,就須要定義兩次,同時,數組長度也受到限制,即便是動態定義數組長度,可是長度依然須要固定在某一個範圍內,不方便也不靈活。數據結構
若是說我想要消除上面的這個限制和不方便應該怎麼辦呢?Java是否提供了相應的解決方法。答案是確定的,這就是Java容器,java容器是javaAPI所提供的一系列類的實例,用於在程序中存放對象,主要位於Java.util包中,其長度不受限制,類型不受限制,你在存放String類的時候依然可以存放Integer類,二者不會衝突。多線程
java類庫中爲咱們定義了不少類。能夠劃分紅 容器類(也稱集合類) 工具類//大致我如今就知道這三種分類……我也不知道還有沒有其餘類型app
集合類是來實現集合操做的;工具類是對集合功能的擴展,其中大部分是static函數,通常沒必要實例化建立對象,而直接調用對集合進行操做。
一/集合類
集合類存放於java.util包中。
集合類存放的都是對象的引用,而非對象自己,出於表達上的便利,咱們稱集合中的對象就是指集合中對象的引用(reference)。
1.集合框架
//以上 圖一
//以上 圖二
//以上 圖三
//以上 圖四
//以上 圖五
從圖二中能夠看出
集合接口:6個接口(短線表示),表示不一樣集合類型,是集合框架的基礎。主要是 list列表 map映射 set集 三大類。
抽象類:5個抽象類(長虛線表示),對集合接口的部分實現。可擴展爲自定義集合類。//通常不用,通常直接使用實現類。
實現類:8個實現類(實線表示),對接口的具體實現。ArrayList HashMap 等等
在很大程度上,一旦您理解了接口,您就理解了框架。雖然您總要建立接口特定的實現,但訪問實際集合的方法應該限制在接口方法的使用上;所以,容許您更改基本的數據結構而沒必要改變其它代碼。
· Collection 接口是一組容許重複的對象。
· Set 接口繼承 Collection,但不容許重複,使用本身內部的一個排列機制。
· List 接口繼承 Collection,容許重複,以元素安插的次序來放置元素,不會從新排列。
· Map接口是一組成對的鍵-值對象,即所持有的是key-value pairs。Map中不能有重複的key。擁有本身的內部排列機制。
· 容器中的元素類型都爲Object。從容器取得元素時,必須把它轉換成原來的類型。
Collection是List和Set兩個接口的基接口
List在Collection之上增長了"有序"
Set在Collection之上增長了"惟一"
而ArrayList是實現List的類...因此他是有序的.它裏邊存放的元素在排列上存在必定的前後順序,並且ArrayList是採用數組存放元素。另外一種List LinkedList採用的則是鏈表。
Collection和Map接口之間的主要區別在於:Collection中存儲了一組對象,而Map存儲關鍵字/值對。在Map對象中,每個關鍵字最多有一個關聯的值。
Map:不能包括兩個相同的鍵,一個鍵最多能綁定一個值。null能夠做爲鍵,這樣的鍵只有一個;能夠有一個或多個鍵所對應的值爲null。當get()方法返回null值時,便可以表示Map中沒有該鍵,也能夠表示該鍵所對應的值爲null。所以,在Map中不能由get()方法來判斷Map中是否存在某個鍵,而應該用containsKey()方法來判斷。
繼承Map的類有:HashMap,HashTable
HashMap:Map的實現類,缺省狀況下是非同步的,能夠經過Map Collections.synchronizedMap(Map m)來達到線程同步
HashTable:Dictionary的子類,缺省是線程同步的。不容許關鍵字或值爲null
當元素的順序很重要時選用TreeMap,當元素沒必要以特定的順序進行存儲時,使用HashMap。Hashtable的使用不被推薦,由於HashMap提供了全部相似的功能,而且速度更快。當你須要在多線程環境下使用時,HashMap也能夠轉換爲同步的
2.數組與容器
數組與其它容器的區別體如今三個方面:效率,類型識別以及能夠持有primitives。數組是Java提供的,能隨機存儲和訪問reference序列的諸多方法中的,最高效的一種。數組是一個簡單的線性序列,因此它能夠快速的訪問其中的元素。可是速度是有代價的;當你建立了一個數組以後,它的容量就固定了,並且在其生命週期裏不能改變。也許你會提議先建立一個數組,等到快不夠用的時候,再建立一個新的,而後將舊的數組裏的reference所有導到新的裏面。其實(咱們之後會講的)ArrayList就是這麼作的。可是這種靈活性所帶來的開銷,使得ArrayList的效率比起數組有了明顯降低。
還有一些泛型容器類包括List,Set和Map。他們處理對象的時候就好像這些對象都沒有本身的具體類型同樣。也就是說,容器將它所含的元素都當作是(Java中全部類的根類)Object的。這樣你只須要建一種容器,就能把全部類型的對象全都放進去。從這個角度來看,這種做法很不錯(只是苦了primitive。若是是常量,你還能夠用Java的primitive的Wrapper類;若是是變量,那就只能放在你本身的類裏了)。與其餘泛型容器相比,這裏體現數組的第二個優點:建立數組的時候,你也同時指明瞭它所持有的對象的類型(這又引出了第三點--數組能夠持有primitives,而容器卻不行)。也就是說,它會在編譯的時候做類型檢查,從而防止你插入錯誤類型的對象,或者是在提取對象的時候把對象的類型給搞錯了。Java在編譯和運行時都能阻止你將一個不恰當的消息傳給對象。全部這並非說使用容器就有什麼危險,只是若是編譯器可以幫你指定,那麼程序運行會更快,最終用戶也會較少收到程序運行異常的騷擾。
當你事先不知道要存放數據的個數,或者你須要一種比數組下標存取機制更靈活的方法時,你就須要用到集合類。
3.詳細介紹
有序否 |
容許元素重複否 |
||
Collection |
否 |
是 |
|
List |
是 |
是 |
|
Set |
AbstractSet |
否 |
否 |
HashSet |
|||
TreeSet |
是(用二叉樹排序) |
||
Map |
AbstractMap |
否 |
使用key-value來映射和存儲數據,Key必須唯一,value能夠重複 |
HashMap |
|||
TreeMap |
是(用二叉樹排序)
|
(1)集 (Set):口袋
集(set)是最簡單的一種集合,它的對象不按特定方式排序,只是簡單的把對象加入集合中,就像往口袋裏放東西。
對集中成員的訪問和操做是經過集中對象的引用進行的,因此集中不能有重複對象。
集也有多種變體,能夠實現排序等功能,如TreeSet,它把對象添加到集中的操做將變爲按照某種比較規則將其插入到有序的對象序列中。它實現的是SortedSet接口,也就是加入了對象比較的方法。經過對集中的對象迭代,咱們能夠獲得一個升序的對象集合。
(2)列表 (List):列表
列表的主要特徵是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,固然,它與根本沒有順序的集是不一樣的。
列表在數據結構中分別表現爲:數組和向量、鏈表、堆棧、隊列。
關於實現列表的集合類,是咱們平常工做中常常用到的,將在後邊的筆記詳細介紹。
(3)映射 (Map):鍵值對
映射與集或列表有明顯區別,映射中每一個項都是成對的。映射中存儲的每一個對象都有一個相關的關鍵字(Key)對象,關鍵字決定了對象在映射中的存儲位置,檢索對象時必須提供相應的關鍵字,就像在字典中查單詞同樣。關鍵字應該是惟一的。
關鍵字自己並不能決定對象的存儲位置,它須要對過一種散列(hashing)技術來處理,產生一個被稱做散列碼(hash code)的整數值,散列碼一般用做一個偏置量,該偏置量是相對於分配給映射的內存區域起始位置的,由此肯定關鍵字/對象對的存儲位置。理想狀況下,散列處理應該產生給定範圍內均勻分佈的值,並且每一個關鍵字應獲得不一樣的散列碼。
集合類簡介
java.util中共有13個類可用於管理集合對象,它們支持集、列表或映射等集合,如下是這些類的簡單介紹
集:
HashSet: 使用HashMap的一個集的實現。雖然集定義成無序,但必須存在某種方法能至關高效地找到一個對象。使用一個HashMap對象實現集的存儲和檢索操做是在固定時間內實現的.
TreeSet: 在集中以升序對對象排序的集的實現。這意味着從一個TreeSet對象得到第一個迭代器將按升序提供對象。TreeSet類使用了一個TreeMap.
列表:
Vector: 實現一個相似數組同樣的表,自動增長容量來容納你所需的元素。使用下標存儲和檢索對象就象在一個標準的數組中同樣。你也能夠用一個迭代器從一個Vector中檢索對象。Vector是惟一的同步容器類??當兩個或多個線程同時訪問時也是性能良好的。(同步的含義:即同時只能一個進程訪問,其餘等待)
Stack: 這個類從Vector派生而來,而且增長了方法實現棧??一種後進先出的存儲結構。
LinkedList: 實現一個鏈表。由這個類定義的鏈表也能夠像棧或隊列同樣被使用。
ArrayList: 實現一個數組,它的規模可變而且能像鏈表同樣被訪問。它提供的功能相似Vector類但不一樣步。
映射:
HashTable: 實現一個映象,全部的鍵必須非空。爲了能高效的工做,定義鍵的類必須實現hashcode()方法和equal()方法。這個類是前面java實現的一個繼承,而且一般能在實現映象的其餘類中更好的使用。
HashMap: 實現一個映象,容許存儲空對象,並且容許鍵是空(因爲鍵必須是惟一的,固然只能有一個)。
WeakHashMap: 實現這樣一個映象:一般若是一個鍵對一個對象而言再也不被引用,鍵/對象對將被捨棄。這與HashMap造成對照,映象中的鍵維持鍵/對象對的生命週期,儘管使用映象的程序再也不有對鍵的引用,而且所以不能檢索對象。
TreeMap: 實現這樣一個映象,對象是按鍵升序排列的。
下圖是集合類所實現的接口之間的關係:
Set和List都是由公共接口Collection擴展而來,因此它們均可以使用一個類型爲Collection的變量來引用。這就意味着任何列表或集構成的集合均可以用這種方式引用,只有映射類除外(但也不是徹底排除在外,由於能夠從映射得到一個列表。)因此說,把一個列表或集傳遞給方法的標準途徑是使用Collection類型的參數。
List接口
List是有序的Collection,使用此接口可以精確的控制每一個元素插入的位置。用戶可以使用索引(元素在List中的位置,相似於數組下標)來訪問List中的元素,這相似於Java的數組。
和下面要提到的Set不一樣,List容許有相同的元素。
除了具備Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,容許添加,刪除,設定元素,還能向前或向後遍歷。
實現List接口的經常使用類有LinkedList,ArrayList,Vector和Stack。
ArrayList類
ArrayList實現了可變大小的數組。它容許全部元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間爲常數。可是add方法開銷爲分攤的常數,添加n個元素須要O(n)的時間。其餘的方法運行時間爲線性。
每一個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨着不斷添加新元素而自動增長,可是增加算法並無定義。ArrayList當須要插入大量元素時,在插入前能夠調用ensureCapacity方法來增長ArrayList的容量以提升插入效率。
和LinkedList同樣,ArrayList也是非同步的(unsynchronized)。
Map接口
請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每一個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容能夠被看成一組key集合,一組value集合,或者一組key-value映射。
HashMap類
HashMap和Hashtable相似,不一樣之處在於HashMap是非同步的,而且容許null,即null value和null key。,可是將HashMap視爲Collection時(values()方法可返回Collection),其迭代子操做時間開銷和HashMap的容量成比例。所以,若是迭代操做的性能至關重要的話,不要將HashMap的初始化容量設得太高,或者load factor太低。
----------------------------------------------------------------------------
1.-------------------->
List是接口,List特性就是有序,會確保以必定的順序保存元素.
ArrayList是它的實現類,是一個用數組實現的List.
Map是接口,Map特性就是根據一個對象查找對象.
HashMap是它的實現類,HashMap用hash表實現的Map,就是利用對象的hashcode(hashcode()是Object的方法)進行快速(Hash)散列查找.(關於散列查找,能夠參看<<數據結構>>)
2.-------------------->
通常狀況下,若是沒有必要,推薦代碼只同List,Map接口打交道.
好比:List list = new ArrayList();
這樣作的緣由是list就至關因而一個泛型的實現,若是想改變list的類型,只須要:
List list = new LinkedList();//LinkedList也是List的實現類,也是ArrayList的兄弟類
這樣,就不須要修改其它代碼,這就是接口編程的優雅之處.
另外的例子就是,在類的方法中,以下聲明:
private void doMyAction(List list){}
這樣這個方法能處理全部實現了List接口的類,必定程度上實現了泛型函數.
3.--------------------->
若是開發的時候以爲ArrayList,HashMap的性能不能知足你的須要,能夠經過實現List,Map(或者Collection)來定製你的自定義類
二/工具類——「低耦合」
其實理解了集合框架也就差很少了。工具類,正如上面說過的,是對集合功能的擴展,其中大部分是static函數,通常沒必要實例化建立對象,而直接調用對集合進行操做。
接下來爲了方便理解,以Array Arrays ArraysList
Array:認真看api索引的話,Array有兩個。一個是sql中的接口,一個是類,咱們在這裏說的是這個類。
Arrays:對數組的一些列操做。
ArrayList是一個容器。
1)精闢闡述:
能夠將 ArrayList想象成一種「會自動擴增容量的Array」。
2)Array([]):最高效;可是其容量固定且沒法動態改變;
ArrayList: 容量可動態增加;但犧牲效率;
3)建議:
基於效率和類型檢驗,應儘量使用Array,沒法肯定數組大小時才使用ArrayList!
不過當你試着解決更通常化的問題時,Array的功能就可能過於受限。
4)Java中一切皆對象,Array也是對象。不論你所使用得Array型別爲什麼,
Array名稱自己其實是個reference,指向heap以內得某個實際對象。
這個對象可經由「Array初始化語法」被自動產生,也能夠以new表達式手動產生。
5)Array可作爲函數返回值,由於它自己是對象的reference;
6)對象數組與基本類型數組在運用上幾乎如出一轍,惟一差異在於,前者持有得是reference,後者直接持有基本型別之值;
例如:
string [] staff=new string[100];
int [] num=new int[10];
7)容器所持有的實際上是一個個reference指向Object,進而才能存儲任意型別。固然這不包括基本型別,由於基本型別並不繼承自任何classes。
8)面對Array,咱們能夠直接持有基本型別數值的Array(例如:int [] num;),也能夠持有reference(指向對象)的Array;可是容器類僅能持有reference(指向對象),若要將基本型別置於容器內,須要使用wrapper類。可是wrapper類使用起來可能不很容易上手,此外,primitives Array的效率比起「容納基本型別以外覆類(的reference)」的容器好太多了。
固然,若是你的操做對象是基本型別,並且須要在空間不足時自動擴增容量,Array便不適合,此時就得使用外覆類的容器了。
9)某些狀況下,容器類即便沒有轉型至原來的型別,仍然能夠運做無誤。有一種狀況尤爲特別:編譯器對String class提供了一些額外的支持,使它能夠平滑運做。
10)對數組的一些基本操做,像排序、搜索與比較等是很常見的。所以在Java中提供了Arrays類協助這幾個操做:sort(),binarySearch(),equals(),fill(),asList().
不過Arrays類沒有提供刪除方法,而ArrayList中有remove()方法,不知道是不是不須要在Array中作刪除等操做的緣由(由於此時應該使用鏈表)。
11)ArrayList的使用也很簡單:產生ArrayList,利用add()將對象置入,利用get(i)配合索引值將它們取出。這一切就和Array的使用方式徹底相同,只不過少了[]而已。
2.參考資料:
1)效率:
數組擴容是對ArrayList效率影響比較大的一個因素。
每當執行Add、AddRange、Insert、InsertRange等添加元素的方法,都會檢查內部數組的容量是否不夠了,若是是,它就會以當前容量的兩倍來從新構建一個數組,將舊元素Copy到新數組中,而後丟棄舊數組,在這個臨界點的擴容操做,應該來講是比較影響效率的。
ArrayList是Array的複雜版本
ArrayList內部封裝了一個Object類型的數組,從通常的意義來講,它和數組沒有本質的差異,甚至於ArrayList的許多方法,如Index、IndexOf、Contains、Sort等都是在內部數組的基礎上直接調用Array的對應方法。
2)類型識別:
ArrayList存入對象時,拋棄類型信息,全部對象屏蔽爲Object,編譯時不檢查類型,可是運行時會報錯。
ArrayList與數組的區別主要就是因爲動態增容的效率問題了
3)ArrayList能夠存任何Object,如String等。
引用:
http://www.cnblogs.com/mengdd/archive/2013/01/19/2868095.html
http://www.blogjava.net/leishengwei/archive/2012/03/20/372246.html
http://my.oschina.net/wisedream/blog/137045
http://www.cnblogs.com/eflylab/archive/2007/01/20/625216.html
http://www.blogjava.net/EvanLiu/archive/2007/11/12/159884.html
http://www.cnblogs.com/wuyuegb2312/p/3867293.html
http://blog.sina.com.cn/s/blog_5ce1fe770100b0ay.html Java中Array與ArrayList的主要區別