Java Collections Framework是Java提供的對集合進行定義,操做,和管理的包含一組接口,類的體系結構。php
Java集合框架的基本接口/類層次結構:html
java.util.Collection [I] +--java.util.List [I] +--java.util.ArrayList [C] +--java.util.LinkedList [C] +--java.util.Vector [C] +--java.util.Stack [C] +--java.util.Set [I] +--java.util.HashSet [C] +--java.util.SortedSet [I] +--java.util.TreeSet [C] java.util.Map [I] +--java.util.SortedMap [I] +--java.util.TreeMap [C] +--java.util.Hashtable [C] +--java.util.HashMap [C] +--java.util.LinkedHashMap [C] +--java.util.WeakHashMap [C]
其中I表示接口,C表示實現類java
在實際開發中,須要將使用的對象存儲於特定數據結構的容器中。JDK提供了這樣的容器---集合(Collection)。Collection是一個接口,定義了集合相關的操做方法,其有兩個子接口:List與Setc++
List:可重複集合 Set:不可重複的集合 其中判斷元素是否重複,取決於元素的equals()比較的結果
集合中存儲的都是引用類型元素,而且集合只保存每一個元素對象的引用,而並不是將元素對象自己存入集合。
objective-c
Collection定義了一個add方法用於向集合中添加新元素。 boolean add(E e) 該方法返會將給定的元素添加進集合,若添加成功,則返回true,不然返回false。
實例1c#
import java.util.ArrayList; import java.util.Collection; public class Test00{ public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c); c.add("a"); c.add("b"); c.add("c"); System.out.println(c); } }
boolean contains(Object o) 該方法用於斷定給定的元素是否被包含在集合中。若包含則返回true,反則返回false。 注意:集合在判斷元素是否被包含在集合中是根據每一個元素的equals方法進行比較的結果。 一般有必要重寫equals()保證contains()方法的合理結果
實例2:數組
import java.util.ArrayList; import java.util.Collection; public class Test00{ public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c); c.add("a"); c.add("b"); c.add("c"); System.out.println(c); Collection<String> b = new ArrayList<String>(); b.add("b"); b.add("c"); System.out.println(c.contains(b)); System.out.println(c.contains("b")); c.addAll(b); System.out.println(c); System.out.println(c.contains(b)); System.out.println(c.contains("h")); } }
int size() 該方法用於返回當前集合中的元素總數 void clear() 該方法用於清空當前集合。 boolean isEmpty() 該方法用於斷定當前集合中是否不包含任何元素
實例3 :數據結構
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); System.out.println(c.isEmpty()); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("cpp"); System.out.println("isEmpty : " + c.isEmpty() + ",size : "+ c.size()); c.clear();// 清空該集合 System.out.println("isEmpty : "+ c.isEmpty() + ",size : " + c.size()); } } addAll containsAll boolean addAll(Collection <? extends E> c) 該方法須要咱們傳入一個集合,並將該集合中的全部元素添加到當前集合中。 boolean containsAll(Collection<?> c) 該方法用於斷定當前結合是否包含給定集合中的全部元素,若包含則返回true。
實例4併發
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class Test00{ public static void main(String[] args) { Collection<String> c1 = new ArrayList<String>(); c1.add("java"); c1.add("cpp"); c1.add("php"); c1.add("c#"); c1.add("objective-c"); c1.add("cppc"); System.out.println(c1); Collection<String> c2 = new HashSet<String>(); c2.addAll(c1); System.out.println(c2); Collection<String> c3 =new ArrayList<String>(); c3.add("java"); c3.add("cpp"); System.out.println(c1.containsAll(c3)); } }
Iterator是迭代器,擁有兩個方法框架
迭代器用於遍歷集合元素。獲取迭代器可使用Collection定義的方法:
Iterator iterator()
迭代器Iterator是一個藉口,集合在重寫Collection的iterator()方法時利用內部類提供了迭代器的實現。 Iterator提供了統一的遍歷元素集合的方法,其提供了用於遍歷集合的兩個方法: boolean hasNext():判斷集合是否還有元素能夠遍歷 E next():返回迭代的下一個元素
實例4
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); Iterator<String> iterator = c.iterator(); while(iterator.hasNext()){ String str = iterator.next(); System.out.println(str); } } }
在使用迭代器遍歷集合時,不能經過集合的remove方法刪除集合元素,不然會拋出併發更改異常。咱們能夠經過迭代器自身提供的remove()方法來刪除經過next()迭代出的元素
void remove()
迭代器的刪除方法是在原集合中刪除元素。
這裏須要注意的是:在調用remove方法前必須經過迭代器的next方法迭代過的元素,那麼刪除的就是這個元素。而且不可以再次調用remove方法,除非再次調用next()後方可再次調用。
實例5:
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); Iterator<String> it = c.iterator(); while(it.hasNext()){ String str = it.next(); if(str.indexOf("c")!=-1){ it.remove();// 刪除包含字母c的元素 } } System.out.println(c); } }
Java5.0以後推出了一個新的特性,加強for循環,也成爲新循環。該循環不通用於傳統循環的工做,其只用於遍歷集合或數組。
語法: for(元素類型 e:集合或數組){ 循環體 }
實例7
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); for(String str : c) { System.out.print(str.toUpperCase()+" "); //C# CPP OBJECTIVE-C JAVA PHP } } }
新循環並不是新的語法,而是在編譯過程當中,編譯器會將新循環轉爲迭代器模式。因此新循環本質上是迭代器。
泛型是Java SE5.0引入的特性,泛型的本質是參數化類型。在類、接口、和方法的定義過程當中,所操做的數據類型被傳入的參數指定。
Java泛型機制普遍的應用在集合框架中。全部的集合類型都帶有泛型的參數,這樣在建立集合時能夠指定放入集合中的元素的類型。Java編譯器能夠據此進行類型檢查,這樣能夠減小代碼在運行時出現錯誤的可能性。
List接口是Collection的子接口,用於定義線性表數據結構。能夠講List理解爲存放對象的數組,只不過其元素能夠動態的增長或減小。
List接口的兩個常見實現類爲ArrayList和LinkList,分別用動態數組和鏈表的方式實現了List接口。
能夠認爲ArrayList和LinkedList的方法在邏輯上徹底同樣,只是在性能上有必定差異。ArrayList更適合於隨機訪問,LinkList更適合於插入和刪除。在性能要求不是特別苛刻的情形下能夠忽略這個差異。
List除了繼承Collection定義方法外,還根據其線性表的數據結構定義了一系列的方法,其中最經常使用的就是基於下標的get和set方法
E get(int index) 獲取集合執行下標對應的元素,下標從0開始。 E set(int index,Element) 將給定的元素存入給定位置,並將原位置的元素返回。
實例8
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; public class Test00{ public static void main(String[] args) { List<String> c = new ArrayList<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); for(int i = 0;i<c.size();i++){ System.out.println(c.get(i).toUpperCase()); } String value = c.set(1, "c++"); System.out.println(value);// cpp System.out.println(c);// [java, c++, php, c#, objective-c] c.set(1,c.set(3, c.get(1)));// 交換1和3上的元素位置 由於內層返回的是3位置的元素 System.out.println(c);// [java, c#, php, c++, objective-c] } }
List根據下標的操做還支持插入語刪除操做
void add(int index,Element);
將給定的元素插入到指定位置,原位置及後續元素都順序向後移動。
E remove(int index);
刪除給定位置的元素,並將被刪除的元素返回。
List的toArray方法用於將集合轉換爲數組。但實際上該方法是在Collection中定義的,因此全部的集合都具有這個功能。
其有兩個方法: Object[] toArray() <T>T[] toArray(T[] a)
其中第二個方法是比較經常使用的,咱們能夠傳入一個指定類型的數組,該數組的元素類型與集合的元素類型一致。返回值則是轉換後的數組,該數組會保存集合中的全部元素。
Arrays類中提供了一個靜態方法asList,使用該方法咱們能夠將一個數組轉換爲對應的List集合。
其方法定義爲:
static <T>List<T> asList<T... a>
返回的List的集合元素類型由傳入的數組的元素類型決定。
而且要注意的是,返回的集合咱們不能對其增刪元素。而且對集合的元素進行修改hi影響數組對應的元素。
Collection.sort方法實現排序
Collection是集合的工具類,它提供了不少便於咱們操做集合的方法,其中就有用於集合排序的sort方法。該方法定義爲:
void sort(List<T> list) 該方法的做用是對給定的集合元素進行天然排序。
Collection的sort方法是對集合元素進行天然排序,那麼兩個元素對象之間就必定要有大小之分。這個代銷之分是如何界定的?
實際上,在使用Collection的sort排序的結合都必須是Comparable接口實現類,該接口表示其子類是可比較的,由於實現該接口必須重寫抽象方法:
int compareTo(T t); 該方法返回值要求: 若o1>o2則返回值應>0 若o1<o2則返回值應<0 若o1=o2則返回值由於0
雙向鏈表 雙端效率高
方法
add(數據) 添加數據 get(i) 訪問指定位置的收 remove(i) 移除指定位置的數據 size() 元素的數量 addFirst() 在鏈表首處添加元素 addLast() 在鏈表末尾添加元素 getFirst() 得到第一個元素 getLast() 得到末尾元素 removeFirst() 刪除第一個元素 removeLast() 刪除最後一個元素 iterator() 輔助建立迭代器對象進行設置
LinkedList實例:
import java.lang.reflect.Array; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; public class Test00{ public static void main(String[] args) { LinkedList<String> list = new LinkedList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); list.add("eee"); list.add("fff"); list.add("ggg"); list.add("hhh"); list.add("iii"); list.add("jjj"); list.add("kkk"); list.add("lll"); System.out.println("獲取鏈表數組的大小: "+list.size());// 獲取鏈表的大小 System.out.println("get方法獲取元素 "+list.get(0)); System.out.println("獲取第一個元素"+list.getFirst()); System.out.println("獲取鏈表的以後一個元素 "+list.getLast()); LinkedList<String> list1 = new LinkedList<>(); list1.addAll(list); for(String s1:list1){// 元素遍歷 System.out.println(s1); } // 經過迭代器來遍歷 Iterator<String> iterator = list.iterator(); if(iterator.hasNext()){ String str = iterator.next(); System.out.println(str); } System.out.println("刪除鏈表的第一個元素 "+list.removeFirst()); System.out.println("刪除鏈表的最後一個元素: "+list.removeLast()); System.out.println("找到第一個相等的元素進行刪除 "+list.remove("ddd")); System.out.println("指定刪除鏈表中的某個元素:"+list.remove(4)); System.out.println(list.toArray());// 將list鏈表轉爲數組 Object[] listarr = list.toArray();// 將list轉爲數組,並利用數組的方式進行答應 System.out.println(Arrays.toString(listarr)); } }
6.8 ArrayList和LinkedList的大體區別以下:
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。 2.對於隨機訪問get和set,ArrayList以爲優於LinkedList,由於LinkedList要移動指針。 3.對於新增和刪除操做add和remove,LinedList比較佔優點,由於ArrayList要移動數據
示例以下:
import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; public class Test00{ static final int N = 500000; static long timeList(List list){ long start = System.currentTimeMillis(); Object o = new Object(); for(int i = 0;i<N;i++){ list.add(0,o); } return System.currentTimeMillis() - start; } static long readList(List list){ long start = System.currentTimeMillis(); for(int i = 0;i<list.size();i++){ } return System.currentTimeMillis() - start; } static List addList(List list){ Object o = new Object(); for(int i = 0;i<N;i++){ list.add(0,o); } return list; } public static void main(String[] args) { System.out.println("ArrayList添加"+N+"條耗時:"+timeList(new ArrayList())); System.out.println("LinkedList添加"+N+"條耗時"+timeList(new LinkedList())); List list1 = addList(new ArrayList()); List list2 = addList(new LinkedList()); System.out.println("ArrayList查找"+N+"條耗時"+readList(list1)); System.out.println("LinkedList查找"+N+"條記錄耗時"+timeList(list2)); /* 結果以下 ArrayList添加500000條耗時:31141 LinkedList添加500000條耗時1 ArrayList查找500000條耗時15 LinkedList查找500000條記錄耗時3 */ } }
隊列是經常使用的數據結構,能夠將隊列當作特殊的線性表,隊列限制了線性表的訪問方式:只能從線性表 的一端添加(offer)元素,從另外一端取出(poll)元素。 隊列遵循先進先出(FIFO First Input First Output)的原則。 JDK中提供了Queue接口,同時使用LinkedList實現了該接口(選擇LinkList實現Queue的緣由在於 Queue常常要進行添加和刪除的操做,而LinkList在這方面效率較高)。
Queue接口中主要方法以下:
boolean off(E e) 將一個元素添加至隊尾,若是添加成功則返回true。 E poll() 從隊首刪除並返回一個元素。 E peek() 返回隊首的元素(但並不刪除).
Deque是Queue的子接口,定義了所謂的"雙端隊列",即從隊列的兩端分別能夠入隊(offer)和出隊(poll),LinkList實現了該接口。
若是將Deque限制爲只能從一端入隊和出隊,則可實現"棧"(Stack)數據結構,對棧而言,入棧稱之爲push,出棧稱之爲pop。
棧遵循先進後出(FILO First Input Last Output)的原則。
import java.util.LinkedList; import java.util.Queue; public class Test00{ public static void main(String[] args) { Queue<String> queue = new LinkedList<String>(); queue.offer("a");// 將一個對象添加至隊尾,若是添加成功則返回true queue.offer("b"); queue.offer("c"); System.out.println(queue); String str =queue.peek(); System.out.println(str); while(queue.size()>0){ // 從隊首刪除並返回一個元素 str = queue.poll(); System.out.println(str + " "); } } }