Java入門教程十二(集合與泛型)

在 Java 中數組的長度是不可修改的。然而在實際應用的很多情況下,無法確定數據數量。這些數據不適合使用數組來保存,這時候就需要使用集合。

Java 的集合就像一個容器,用來存儲 Java 類的對象。有些容器內部存放的東西在容器內部是不可操作的,像水瓶裡的水,除了將其裝入和倒出之外,就不能再進行別的操作了,但是很容易裝入和倒出;而有些容器內部存放的東西在容器內部是可以操作的,例如,衣櫃裡面擺放的衣服,不僅可以將衣服存放到衣櫃中,還可以將衣服有序地擺放,以便在使用時快速查找,但是卻不容易取出。Java 的集合類比這些容器功能還多,其中有些是方便放入和取出的,有些是方便查找的。在集合中經常會用到泛型來使集合更加安全。

集合

集合類都位於 java.util 包,其中提供了一個表示和操作對象集合的統一構架,包含大量集合接口,以及這些接口的實現類和操作它們的算法。一個集合是一個對象,但它表示一組對象,Java 集合中實際存放的是對象的引用值,不能存放基本數據類型值。

集合中的接口

集合框架是一個類庫的集合,包含實現集合的接口。接口是集合的抽象數據類型,提供對集合中所表示的內容進行單獨操作的可能。

Collection 接口:該接口是最基本的集合接口,一個 Collection 代表一個元素。

List 接口:該接口實現了 Collection 接口。List 是有序集合,允許有相同的元素。使用 List 能夠精確地控制每個元素插入的位置,用戶能夠使用索引(元素在 List 中的位置,類似於數組下標)來訪問 List 中的元素,與數組類似。

Set 接口:該接口也實現了 Collection 接口。它不能包含重複的元素,SortedSet 是按升序排列的 Set 集合。

Map 接口:包含鍵值對,Map 不能包含重複的鍵。SortedMap 是一個按升序排列的 Map 集合。

接口實現類

Java 平臺提供了許多數據集接口的實現類。例如實現 Set 接口的常用類有 HashSet 和 TreeSet,它們都可以容納所有類型的對象,但是不能保證序列順序永久不變

實現 List 接口的常用類有 ArrayList 和 LinkedList,它們也可以容納所有類型的對象包括 null,並且都保證元素的存儲位置。

實現 Map 映射的類是 HashMap,可實現一個鍵到值的映射。

HashSet:為優化査詢速度而設計的 Set。它是基於 HashMap 實現的,HashSet 底層使用 HashMap 來保存所有元素,實現比較簡單。

TreeSet:該類不僅實現了 Set 接口,還實現了 java.util.SortedSet 接口,該實現類是一個有序的 Set,這樣就能從 Set 裡面提取一個有序序列。

ArrayList:一個用數組實現的 List,能進行快速的隨機訪問,效率高而且實現了可變大小的數組。

LinkedList:對順序訪問進行了優化,但隨機訪問的速度相對較慢。此外它還有 addFirst()、addLast()、getFirst()、getLast()、removeFirst() 和 removeLast() 等方法,能把它當成棧(Stack)或隊列(Queue)來用。

Collection接口

Collection 接口是 List 接口和 Set 接口的父接口,通常情況下不被直接使用。Collection 接口定義了一些通用的方法,通過這些方法可以實現對集合的基本操作。因為 List 接口和 Set 接口繼承自 Collection 接口,所以也可以調用這些方法

boolean add(E e) 向集合中添加一個元素,E 是元素的數據類型 boolean addAll(Collection c) 向集合中添加集合 c 中的所有元素 void clear() 刪除集合中的所有元素 boolean contains(Object o) 判斷集合中是否存在指定元素 boolean containsAll(Collection c) 判斷集合中是否包含集合 c 中的所有元素 boolean isEmpty() 判斷集合是否為空 Iteratoriterator() 返回一個 Iterator 對象,用於遍歷集合中的元素 boolean remove(Object o) 從集合中刪除一個指定元素 boolean removeAll(Collection c) 從集合中刪除所有在集合 c 中出現的元素 boolean retainAll(Collection c) 僅僅保留集合中所有在集合 c 中出現的元素 int size() 返回集合中元素的個數 Object[] toArray() 返回包含此集合中所有元素的數組 public static void main(Strmg[] args) { ArrayList list1=new ArrayList(); //創建集合 iist1 ArrayList list2=new ArrayList(); //創建集合 Iist2 list1.add("one"); //向 list1 添加一個元素 list1.add("two"); //向 list1 添加一個元素 list2.addAll(list1); //將 list1 的所有元素添加到 list2 list2.remove(0); //刪除第一個元素 }

pist集合

List 接口實現了 Collection 接口,它主要有兩個實現類:ArrayList 類和 LinkedList 類。在 List 集合中允許出現重複元素。與 Set 集合不同的是,在 List 集合中的元素是有序的,可以根據索引位置來檢索 List 集合中的元素,第一個添加到 List 集合中的元素的索引為 0,第二個為 1,依此類推

ArrayList 類

ArrayList 類提供了快速的基於索引的成員訪問方式,對尾部成員的增加和刪除支持較好。使用 ArrayList 創建的集合,允許對集合中的元素進行快速的隨機訪問

ArrayList():構造一個初始容量為 10 的空列表。 ArrayList(Collectionc):構造一個包含指定 Collection 的元素的列表,這些元素是按照該 Collection 的迭代器返回它們的順序排列的。

ArrayList 類除了包含 Collection 接口中的所有方法之外,還包括 List 接口

E get(int index)獲取此集合中指定索引位置的元素,E 為集合中元素的數據類型

int index(Object o)返回此集合中第一次出現指定元素的索引,如果此集合不包含該元

素,則返回 -1

int lastIndexOf(Obj ect o)返回此集合中最後一次出現指定元素的索引,如果此集合不包含該

元素,則返回 -1

E set(int index, E element)將此集合中指定索引位置的元素修改為 element 參數指定的對象。

此方法返回此集合中指定索引位置的原元素

List subList(int fromlndex, int tolndex)返回一個新的集合,新集合中包含 fromlndex 和 tolndex 索引之間的所有元素。包含 fromlndex 處的元素,不包含 tolndex 索引處的元素

List list = new ArrayList();

list.add("1");

list.add("2");

list.add("3");

list.add("4");

list.get(0);//得到1

List sublist=new ArrayList();

sublist=list.subList(0,2); //subList 為1,2

LinkList類

LinkedList 類採用鏈表結構保存對象,這種結構的優點是便於向集合中插入或者刪除元素。需要頻繁向集合中插入和刪除元素時,使用 LinkedList 類比 ArrayList 類效果高

LinkedList 類除了包含 Connection 接口和 List 接口

void addFirst(E e) 將指定元素添加到此集合的開頭 void addLast(E e) 將指定元素添加到此集合的末尾 E getFirst() 返回此集合的第一個元素 E getLast() 返回此集合的最後一個元素 E removeFirst() 刪除此集合中的第一個元素 E removeLast() 刪除此集合中的最後一個元素 ``` LinkedList products=new LinkedList(); //創建集合對象 String product1=new String("product1"); String product2=new String("product2"); products.getFirst();//得到product1

Set集合

Set 集合也實現了 Collection 接口,它主要有兩個實現類:HashSet 類和 TreeSet類。Set 集合中的對象不按特定的方式排序,只是簡單地把對象加入集合,集合中不能包含重複的對象,並且最多隻允許包含一個 null 元素

HashSet

HashSet 類是按照哈希算法來存儲集合中的元素,使用哈希算法可以提高集合元素的存儲速度,當向 Set 集合中添加一個元素時,HashSet 會調用該元素的 hashCode() 方法,獲取其哈希碼,然後根據這個哈希碼計算出該元素在集合中的存儲位置,

HashSet():構造一個新的空的 Set 集合。 HashSet(Collection extends E>c):構造一個包含指定 Collection 集合元素的新 Set 集合。其中,“< >”中的 extends 表示 HashSet 的父類,即指明該 Set 集合中存放的集合元素類型。c 表示其中的元素將被存放在此 Set 集合中。 HashSet hs=new HashSet(); //調用無參的構造函數創建HashSet對象 HashSet hss=new HashSet(); //創建泛型的 HashSet 集合對象 String name=new String("HelloWorld"); String name1=new String("HelloWorld1"); hss(name); hss(name1);

如果向 Set 集合中添加兩個相同的元素,則後添加的會覆蓋前面添加的元素,即在 Set 集合中不會出現相同的元素

TreeSet

TreeSet 類同時實現了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以實現對集合升序排序。TreeSet 只能對實現了 Comparable 接口的類對象進行排序,因為 Comparable 接口中有一個 compareTo(Object o) 方法用於比較兩個對象的大小

包裝類(BigDecimal、Biglnteger、 Byte、Double、 Float、Integer、Long 及 Short) 按數字大小比較 Character 按字符的 Unicode 值的數字大小比較 String 按字符串中字符的 Unicode 值的數字大小比較

TreeSet 類除了實現 Collection 接口的所有方法之外,還有以下方法

E first() 返回此集合中的第一個元素。其中,E 表示集合中元素的數據 類型 E last() 返回此集合中的最後一個元素 E poolFirst() 獲取並移除此集合中的第一個元素 E poolLast() 獲取並移除此集合中的最後一個元素 SortedSet subSet(E fromElement,E toElement) 返回一個新的集合,新集合包含原集合中 fromElement 對象與 toElement 對象之間的所有對象。包含 fromElemen t對象,不包含 toElement 對象 SortedSet headSet tailSet(E fromElement) 返回一個新的集合,新集合包含原集合中 fromElement 對象之後的所有對 象。包含 fromElement 對象 TreeSet treeSet=new TreeSet(); treeSet.add(0.02); treeSet.add(0.01); treeSet.add(0.03); for(int i=0;i headTreeSet =scores.headSet(0.02); //headTreeSet內只有0.01

自然排序時只能向 TreeSet 集合中添加相同數據類型的對象,否則會拋出 ClassCastException 異常

Map集合

Map 是一種鍵-值對(key-value)集合,Map 集合中的每一個元素都包含一個鍵對象和一個值對象。其中,鍵對象不允許重複,而值對象可以重複,並且值對象還可以是 Map 類型的,Map 接口主要有兩個實現類:HashMap 類和 TreeMap 類。其中,HashMap 類按哈希算法來存取鍵對象,而 TreeMap 類可以對鍵對象進行排序

Map 接口中提供的常用方法

V get(Object key)返回 Map 集合中指定鍵對象所對應的值。V 表示值的數據類型

V put(K key, V value)向 Map 集合中添加鍵-值對,返回 key 以前對應的 value,如果沒有, 則返回 null

V remove(Object key)從 Map 集合中刪除 key 對應的鍵-值對,返回 key 對應的 value,如 果沒有,則返回null

Set entrySet()返回 Map 集合中所有鍵-值對的 Set 集合,此 Set 集合中元素的數據 類型為 Map.Entry

Set keySet()返回 Map 集合中所有鍵對象的 Set 集合

Map map=new HashMap();

map.put("1","HelloWorld");

map.put("2","HelloWorld");

Collection類

Collections 類提供了許多操作集合的靜態方法,藉助這些靜態方法可以實現集合元素的排序、填充和複製等操作

正向排序

sort() 方法主要有如下兩種重載形式。

void sort(List list):根據元素的自然順序對集合中的元素進行升序排序。

void sort(List list,Comparator comparator):按 comparator 參數指定的排序方式對集合中的元素進行排序。

List test=new ArrayList();

test.add(2);

test.add(1);

test.add(3);

Collections.sort(test); //此時數組為1,2,3

逆向排序

調用 reverse() 靜態方法可以對指定集合元素進行逆向排序

void reverse(List list) //對集合中的元素進行反轉排序 List test=new ArrayList(); test.add(2); test.add(1); test.add(3); Collections.reverse(test); //此時數組為3,2,1

複製

Collections 類的 copy() 靜態方法用於將指定集合中的所有元素複製到另一個集合中

void copy(List super T> dest,List extends T> src)

List srcList=new ArrayList();

destList.add("1");

destList.add("2");

List destList=new ArrayList();

Collections.copy(destList,srcList);//此時destList為1,2

填充

Collections 類的 fill() 靜態方法可以對指定集合的所有元素進行填充操作

void fill(List super T> list,T obj) //使用指定元素替換指定列表中的所有元素 List test=new ArrayList(); test.add("1"); test.add("2"); Collections.fill(srcList,"0"); //此時List裡全是0

泛型

泛型可以在編譯的時候檢查類型安全,並且所有的強制轉換都是自動和隱式的,提高了代碼的重用率。

泛型集合

泛型本質上是提供類型的“類型參數”,也就是參數化類型。我們可以為類、接口或方法指定一個類型參數,通過這個參數限制操作的數據類型,從而保證類型轉換的絕對安全。

public class Person{ private String name; public Person(String _name) { this.name=_name; } } Map persons=new HashMap(); //定義泛型 Map 集合 persons.add(new Person("HelloWorld"));

Map persons =new HashMap();”創建了一個鍵類型為 Integer、值類型為 Person 的泛型集合,即指明瞭該 Map 集合中存放的鍵必須是 Integer 類型、值必須為 Person 類型,否則編譯出錯。

Person preson = persons.get(0);//在獲取 Map 集合中的元素時,不需要將"persons.get(id);"獲取的值強制轉換為 Person 類型,程序會隱式轉換

泛型類

除了可以定義泛型集合之外,還可以直接限定泛型類的類型參數。

public class class_name{} //泛型類一般用於類中的屬性類型不確定的情況下。 private data_type1 property_name1;

在實例化泛型類時,需要指明泛型類中的類型參數,並賦予泛型類屬性相應類型的值

public class Person{ private T param; public T getParam(){ return param; } public void setParam(T _param){ this. param = _param; } } public class Employee{ //類型體 } public static void main(String[] args){ //約束為整形 Person intergerPerson = new Person(); intergerPerson. setParam(1); //約束為字符串類型 Person intergerPerson1 = new Person(); intergerPerson1. setParam("String"); //除基礎類型外,也可以約束為自定義類型 Person intergerPerson2 = new Person(); intergerPerson1. setParam(new Employee()); }

泛型類中的類型參數可以有多個

public class Person{ //使用同上 }

泛型方法

泛型同樣可以在類中包含參數化的方法,而方法所在的類可以是泛型類,也可以不是泛型類。

泛型方法使得該方法能夠獨立於類而產生變化。如果使用泛型方法可以取代類泛型化,那麼就應該只使用泛型方法。另外,對一個 static 的方法而言,無法訪問泛型類的類型參數。因此,如果 static 方法需要使用泛型能力,就必須使其成為泛型方法。

[訪問權限修飾符][static][final]返回值類型方法名([形式參數列表]) public static void Test(T t){ } String helloWorld = "HelloWorld"; Test("HelloWorld");