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

韭菜Java發表於2019-06-11

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

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

集合

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

集合中的介面

集合框架是一個類庫的集合,包含實現集合的介面。介面是集合的抽象資料型別,提供對集合中所表示的內容進行單獨操作的可能。
Collection 介面:該介面是最基本的集合介面,一個 Collection 代表一個元素。
List 介面:該介面實現了 Collection 介面。List 是有序集合,允許有相同的元素。使用 List 能夠精確地控制每個元素插入的位置,使用者能夠使用索引(元素在 List 中的位置,類似於陣列下標)來訪問 List 中的元素,與陣列類似。
Set 介面:該介面也實現了 Collection 介面。它不能包含重複的元素,SortedSet 是按升序排列的 Set 集合。
Map 介面:包含鍵值對,Map 不能包含重複的鍵。SortedMap 是一個按升序排列的 Map 集合。

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

介面實現類

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)來用。

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

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()   判斷集合是否為空
Iterator<E>iterator()   返回一個 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);   //刪除第一個元素 
}

List集合

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

ArrayList 類

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

ArrayList():構造一個初始容量為 10 的空列表。
ArrayList(Collection<?extends E>c):構造一個包含指定 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<E> 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<String> products=new LinkedList<String>();    //建立集合物件
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<String> hss=new HashSet<String>();    //建立泛型的 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<E> subSet(E fromElement,E toElement)  返回一個新的集合,新集合包含原集合中 fromElement 物件與 toElement
物件之間的所有物件。包含 fromElemen t物件,不包含 toElement 物件
SortedSet<E> headSet<E toElement〉   返回一個新的集合,新集合包含原集合中 toElement 物件之前的所有物件。
不包含 toElement 物件
SortedSet<E> tailSet(E fromElement) 返回一個新的集合,新集合包含原集合中 fromElement 物件之後的所有對
象。包含 fromElement 物件
TreeSet<Double> treeSet=new TreeSet<Double>(); 
treeSet.add(0.02);
treeSet.add(0.01);
treeSet.add(0.03);
for(int i=0;i<treeSet.toArray().length;i++)
{
     System.out.print(treeSet.toArray.toArray()[i]); //依次輸出 0.01,0.02,0.03
}
SortedSet<Double> 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<Integer, Person> persons=new HashMap<Integer, Person>();    //定義泛型 Map 集合
persons.add(new Person("HelloWorld"));

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

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

泛型類

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

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

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

public class Person<T>{
    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<Integer> intergerPerson = new Person<Integer>();
    intergerPerson. setParam(1);
    //約束為字串型別
    Person<String> intergerPerson1 = new Person<String>();
    intergerPerson1. setParam("String");
    //除基礎型別外,也可以約束為自定義型別
    Person<Employee> intergerPerson2 = new Person<Employee>();
    intergerPerson1. setParam(new Employee());
}

泛型類中的型別引數可以有多個

public class Person<T,N,S>{
    //使用同上
}

泛型方法

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

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

相關文章