集合框架:用於存儲數據的容器。html
特色:java
集合和數組的區別:算法
數據結構:就是容器中存儲數據的方式。數組
對於集合容器,有不少種。由於每個容器的自身特色不一樣,其實原理在於每一個容器的內部數據結構不一樣。安全
集合容器在不斷向上抽取過程當中。出現了集合體系。數據結構
在使用一個體系時,原則:參閱頂層內容。創建底層對象。併發
Collection框架
|--List:有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素能夠重複。函數
|--Set:無序(存入和取出順序有可能不一致),不能夠存儲重複元素。必須保證元素惟一性。工具
1,添加:
add(object):添加一個元素
addAll(Collection) :添加一個集合中的全部元素。
2,刪除:
clear():將集合中的元素全刪除,清空集合。
remove(obj) :刪除集合中指定的對象。注意:刪除成功,集合的長度會改變。
removeAll(collection) :刪除部分元素。部分元素和傳入Collection一致。
3,判斷:
boolean contains(obj) :集合中是否包含指定元素 。
boolean containsAll(Collection) :集合中是否包含指定的多個元素。
boolean isEmpty():集合中是否有元素。
4,獲取:
int size():集合中有幾個元素。
5,取交集:
boolean retainAll(Collection) :對當前集合中保留和指定集合中的相同的元素。若是兩個集合元素相同,返回flase;若是retainAll修改了當前集合,返回true。
6,獲取集合中全部元素:
Iterator iterator():迭代器
7,將集合變成數組:
toArray();
Iterator
迭代器:是一個接口。做用:用於取集合中的元素。
boolean |
hasNext() 若是仍有元素能夠迭代,則返回 true。 |
next() 返回迭代的下一個元素。 |
|
void |
remove() 從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操做)。 |
每個集合都有本身的數據結構,都有特定的取出本身內部元素的方式。爲了便於操做全部的容器,取出元素。將容器內部的取出方式按照一個統一的規則向外提供,這個規則就是Iterator接口。
也就說,只要經過該接口就能夠取出Collection集合中的元素,至於每個具體的容器依據本身的數據結構,如何實現的具體取出細節,這個不用關心,這樣就下降了取出元素和具體集合的耦合性。
Iterator it = coll.iterator();//獲取容器中的迭代器對象,至於這個對象是是什麼不重要。這對象確定符合一個規則Iterator接口。
public static void main(String[] args) { Collection coll = new ArrayList(); coll.add("abc0"); coll.add("abc1"); coll.add("abc2"); //--------------方式1---------------------- Iterator it = coll.iterator(); while(it.hasNext()) { System.out.println(it.next()); } //---------------方式2用此種---------------------- for(Iterator it = coll.iterator();it.hasNext(); ) { System.out.println(it.next()); } }
List
List自己是Collection接口的子接口,具有了Collection的全部方法。【List的特有方法都有索引,這是該集合最大的特色】
List:有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素能夠重複。
|--ArrayList:底層的數據結構是數組,線程不一樣步,ArrayList替代了Vector,查詢元素的速度很是快。
|--LinkedList:底層的數據結構是鏈表,線程不一樣步,增刪元素的速度很是快。
|--Vector:底層的數據結構就是數組,線程同步的,Vector不管查詢和增刪都巨慢。
1,添加:
add(index,element) :在指定的索引位插入元素。
addAll(index,collection) :在指定的索引位插入一堆元素。
2,刪除:
remove(index) :刪除指定索引位的元素。 返回被刪的元素。
3,獲取:
Object get(index) :經過索引獲取指定元素。
int indexOf(obj) :獲取指定元素第一次出現的索引位,若是該元素不存在返回-1;【因此,經過-1,能夠判斷一個元素是否存在】
int lastIndexOf(Object o) :反向索引指定元素的位置。
List subList(start,end) :獲取子列表。
4,修改:
Object set(index,element) :對指定索引位進行元素的修改。
5,獲取全部元素:
ListIterator listIterator():list集合特有的迭代器。
List集合支持對元素的增、刪、改、查。
List集合由於角標有了本身的獲取元素的方式: 遍歷。
for(int x=0; x<list.size(); x++) { System.out.print("get:"+ list.get(x) +" "); }
在進行list列表元素迭代的時候,若是想要在迭代過程當中,想要對元素進行操做的時候,好比知足條件添加新元素。會發生.ConcurrentModificationException併發修改異常。
致使的緣由是:
集合引用和迭代器引用在同時操做元素,經過集合獲取到對應的迭代器後,在迭代中,進行集合引用的元素添加,迭代器並不知道,因此會出現異常狀況。
如何解決呢?
既然是在迭代中對元素進行操做,找迭代器的方法最爲合適.但是Iterator中只有hasNext,next,remove方法.經過查閱的它的子接口,ListIterator,發現該列表迭代器接口具有了對元素的增、刪、改、查的動做。
ListIterator是List集合特有的迭代器。
ListIterator it = list.listIterator;//取代Iterator it = list.iterator;
方法摘要 |
|
void |
|
boolean |
hasNext() 以正向遍歷列表時,若是列表迭代器有多個元素,則返回 true(換句話說,若是 next 返回一個元素而不是拋出異常,則返回 true)。 |
boolean |
hasPrevious() 若是以逆向遍歷列表,列表迭代器有多個元素,則返回 true。 |
next() 返回列表中的下一個元素。 |
|
int |
nextIndex() 返回對 next 的後續調用所返回元素的索引。 |
previous() 返回列表中的前一個元素。 |
|
int |
previousIndex() 返回對 previous 的後續調用所返回元素的索引。 |
void |
remove() 從列表中移除由 next 或 previous 返回的最後一個元素(可選操做)。 |
void |
可變長度數組的原理:
當元素超出數組長度,會產生一個新數組,將原數組的數據複製到新數組中,再將新的元素添加到新數組中。
注意:對於list集合,底層判斷元素是否相同,其實用的是元素自身的equals方法完成的。因此建議元素都要複寫equals方法,創建元素對象本身的比較相同的條件依據。
LinkedList 的特有方法:
Set
Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一種,迭代器。
|--HashSet:底層數據結構是哈希表,線程是不一樣步的。無序,高效;
HashSet集合保證元素惟一性:經過元素的hashCode方法,和equals方法完成的。
1.當元素的hashCode值相同時,才繼續判斷元素的equals是否爲true。
若是爲true,那麼視爲相同元素,不存。若是爲false,那麼存儲。
2.若是hashCode值不一樣,那麼不判斷equals,從而提升對象比較的速度。
|--LinkedHashSet:有序,hashset的子類。
|--TreeSet:對Set集合中的元素的進行指定順序的排序。不一樣步。TreeSet底層的數據結構就是二叉樹。
哈希表:
1,對對象元素中的關鍵字(對象中的特有數據),進行哈希算法的運算,並得出一個具體的算法值,這個值稱爲哈希值。
2,哈希值就是這個元素的位置。
3,若是哈希值出現衝突,再次判斷這個關鍵字對應的對象是否相同。若是對象相同,就不存儲,由於元素重複。若是對象不一樣,就存儲,在原來對象的哈希值基礎 +1順延。
4,存儲哈希值的結構,咱們稱爲哈希表。
5,既然哈希表是根據哈希值存儲的,爲了提升效率,最好保證對象的關鍵字是惟一的。
這樣能夠儘可能少的判斷關鍵字對應的對象是否相同,提升了哈希表的操做效率。
TreeSet
用於對Set集合進行元素的指定順序排序,排序須要依據元素自身具有的比較性。
若是元素不具有比較性,在運行時會發生ClassCastException異常。
因此須要元素實現Comparable接口,強制讓元素具有比較性,複寫compareTo方法。
依據compareTo方法的返回值,肯定元素在TreeSet數據結構中的位置。
TreeSet方法保證元素惟一性的方式:就是參考比較方法的結果是否爲0,若是return 0,視爲兩個對象重複,不存。
注意:在進行比較時,若是判斷元素不惟一,好比,同姓名,同年齡,才視爲同一我的。
在判斷時,須要分主要條件和次要條件,當主要條件相同時,再判斷次要條件,按照次要條件排序。
TreeSet集合排序的兩種方式,Comparable和Comparator區別:
1:讓元素自身具有比較性,須要元素對象實現Comparable接口,覆蓋compareTo方法。
2:讓集合自身具有比較性,須要定義一個實現了Comparator接口的比較器,並覆蓋compare方法,並將該類對象做爲實際參數傳遞給TreeSet集合的構造函數。
第二種方式較爲靈活。
Map集合
|--Hashtable:底層是哈希表數據結構,是線程同步的。不能夠存儲null鍵,null值。
|--HashMap:底層是哈希表數據結構,是線程不一樣步的。能夠存儲null鍵,null值。替代了Hashtable.
|--TreeMap:底層是二叉樹結構,能夠對map集合中的鍵進行指定順序的排序。
Map集合存儲和Collection有着很大不一樣:
Map中的存儲的一對元素:一個是鍵,一個是值,鍵與值之間有對應(映射)關係。
特色:要保證map集合中鍵的惟一性。
Map經常使用方法:
1,添加。
put(key,value):當存儲的鍵相同時,新的值會替換老的值,並將老值返回。若是鍵沒有重複,返回null。
void putAll(Map);
2,刪除。
void clear():清空
value remove(key) :刪除指定鍵。
3,判斷。
boolean isEmpty():
boolean containsKey(key):是否包含key
boolean containsValue(value) :是否包含value
4,取出。
int size():返回長度
value get(key) :經過指定鍵獲取對應的值。若是返回null,能夠判斷該鍵不存在。固然有特殊狀況,就是在hashmap集合中,是能夠存儲null鍵null值的。
Collection values():獲取map集合中的全部的值。
5,想要獲取map中的全部元素:
原理:map中是沒有迭代器的,collection具有迭代器,只要將map集合轉成Set集合,可使用迭代器了。之因此轉成set,是由於map集合具有着鍵的惟一性,其實set集合就來自於map,set集合底層其實用的就是map的方法。
★ 把map集合轉成set的方法:
Entry就是Map接口中的內部接口,爲何要定義在map內部呢?
entry是訪問鍵值關係的入口,是map的入口,訪問的是map中的鍵值對。
取出map集合中全部元素的方式一:keySet()方法。
能夠將map集合中的鍵都取出存放到set集合中。對set集合進行迭代。迭代完成,再經過get方法對獲取到的鍵進行值的獲取。
Set keySet = map.keySet(); Iterator it = keySet.iterator(); while(it.hasNext()) { Object key = it.next(); Object value = map.get(key); System.out.println(key+":"+value); }
取出map集合中全部元素的方式二:entrySet()方法。
Set entrySet = map.entrySet(); Iterator it = entrySet.iterator(); while(it.hasNext()) { Map.Entry me = (Map.Entry)it.next(); System.out.println(me.getKey()+"::::"+me.getValue()); }
使用集合的技巧:
比較的兩種方式:
一個是Comparable:覆蓋compareTo方法;
一個是Comparator:覆蓋compare方法。
LinkedHashSet,LinkedHashMap:這兩個集合能夠保證哈希表有存入順序和取出順序一致,保證哈希表有序。
集合何時用?
當存儲的是一個元素時,就用Collection。當存儲對象之間存在着映射關係時,就使用Map集合。
保證惟一,就用Set。不保證惟一,就用List。
Collections:它的出現給集合操做提供了更多的功能。這個類不須要建立對象,內部提供的都是靜態方法。
靜態方法:
Collections.sort(list);//list集合進行元素的天然順序排序。 Collections.sort(list,new ComparatorByLen());//按指定的比較器方法排序。 class ComparatorByLen implements Comparator<String> { public int compare(String s1,String s2) { int temp = s1.length()-s2.length(); return temp==0?s1.compareTo(s2):temp; } }
將非同步集合轉成同步集合的方法:Collections中的 XXX synchronizedXXX(XXX);
原理:定義一個類,將集合全部的方法加同一把鎖後返回。
Collection 和 Collections的區別:
Collections是個java.util下的類,是針對集合類的一個工具類,提供一系列靜態方法,實現對集合的查找、排序、替換、線程安全化(將非同步的集合轉換成同步的)等操做。
Collection是個java.util下的接口,它是各類集合結構的父接口,繼承於它的接口主要有Set和List,提供了關於集合的一些操做,如插入、刪除、判斷一個元素是否其成員、遍歷等。
Arrays:
用於操做數組對象的工具類,裏面都是靜態方法。
asList方法:將數組轉換成list集合。
String[] arr = {"abc","kk","qq"}; List<String> list = Arrays.asList(arr);//將arr數組轉成list集合。
將數組轉換成集合,有什麼好處呢?用aslist方法,將數組變成集合;
能夠經過list集合中的方法來操做數組中的元素:isEmpty()、contains、indexOf、set;
注意(侷限性):數組是固定長度,不可使用集合對象增長或者刪除等,會改變數組長度的功能方法。好比add、remove、clear。(會報不支持操做異常UnsupportedOperationException);
若是數組中存儲的引用數據類型,直接做爲集合的元素能夠直接用集合方法操做。
若是數組中存儲的是基本數據類型,asList會將數組實體做爲集合元素存在。
集合變數組:用的是Collection接口中的方法:toArray();
若是給toArray傳遞的指定類型的數據長度小於了集合的size,那麼toArray方法,會自定再建立一個該類型的數據,長度爲集合的size。
若是傳遞的指定的類型的數組的長度大於了集合的size,那麼toArray方法,就不會建立新數組,直接使用該數組便可,並將集合中的元素存儲到數組中,其餘爲存儲元素的位置默認值null。
因此,在傳遞指定類型數組時,最好的方式就是指定的長度和size相等的數組。
將集合變成數組後有什麼好處?限定了對集合中的元素進行增刪操做,只要獲取這些元素便可。
Jdk5.0新特性:
Collection在jdk1.5之後,有了一個父接口Iterable,這個接口的出現的將iterator方法進行抽取,提升了擴展性。
加強for循環:foreach語句,foreach簡化了迭代器。
格式:// 加強for循環括號裏寫兩個參數,第一個是聲明一個變量,第二個就是須要迭代的容器
for( 元素類型 變量名 : Collection集合 & 數組 ) {
…
}
高級for循環和傳統for循環的區別:
高級for循環能夠遍歷map集合嗎?不能夠。可是能夠將map轉成set後再使用foreach語句。
可使用加強for循環迭代數組、collection、map:
String [] arr = {"a", "b", "c"};//數組的靜態定義方式,只試用於數組首次定義的時候 for(String s : arr) { System.out.println(s); }
單列集合 Collection:
List list = new ArrayList();
list.add("aaa");
// 加強for循環, 沒有使用泛型的集合能不能使用加強for循環迭代?能 for(Object obj : list) { String s = (String) obj; System.out.println(s); }
雙列集合 Map:
Map map = new HashMap();
map.put("a", "aaa");
//必須掌握這種方式 Set entrys = map.entrySet(); // 1.得到全部的鍵值對Entry對象 iter = entrys.iterator(); // 2.迭代出全部的entry while(iter.hasNext()) { Map.Entry entry = (Entry) iter.next(); String key = (String) entry.getKey(); // 分別得到key和value String value = (String) entry.getValue(); System.out.println(key + "=" + value); }
加強for循環迭代:原則上map集合是沒法使用加強for循環來迭代的,由於加強for循環只能針對實現了Iterable接口的集合進行迭代;Iterable是jdk5中新定義的接口,就一個方法iterator方法,只有實現了Iterable接口的類,才能保證必定有iterator方法,java有這樣的限定是由於加強for循環內部仍是用迭代器實現的,而實際上,咱們能夠經過某種方式來使用加強for循環。
for(Object obj : map.entrySet()) { Map.Entry entry = (Entry) obj; // obj 依次表示Entry System.out.println(entry.getKey() + "=" + entry.getValue()); }
集合迭代注意問題:在迭代集合的過程當中,不能對集合進行增刪操做(會報併發訪問異常);能夠用迭代器的方法進行操做(子類listIterator:有增刪的方法)。
加強for循環注意問題:在使用加強for循環時,不能對元素進行賦值;
int[] arr = {1,2,3}; for(int num : arr) { num = 0; //不能改變數組的值 } System.out.println(arr[1]); //2
可變參數(...):用到函數的參數上,當要操做的同一個類型元素個數不肯定的時候,但是用這個方式,這個參數能夠接受任意個數的同一類型的數據。
和之前接收數組不同的是: