Java集合類的概述

JYRoy發表於2019-07-16

前述

  複習一下Java中的集合類,是面試筆試中常考察的一個點,特地做的整理。

什麼是集合類?

  集合類,也叫容器類。Java集合類可以用來儲存數量龐大的物件。

  我們和陣列進行對比:

  陣列:儲存基本資料型別,資料型別單一,長度固定,不能動態新增資料。

  集合:儲存的即可是基本型別的值,也可以是物件,可以儲存多種資料型別,長度可變,可以動態新增資料。

 

Java集合類的體系

  Java集合類主要有兩個介面派生而出:Collection和Map。即集合類都是實現的這兩個介面。我們在實際程式設計中經常使用的有 List、Set、Queue(這些是實現的 Collection 介面)HashMap、TreeMap、HashTable(這些實現的 Map 介面)

Collection介面結構

  Collection 介面位於 Java.util 包下,是一個父介面, List、Set、Queue 都是實現的 Collection 介面。Collection 做為父介面提供一些操作集合類的方法,因此它的子介面也有這些方法。

  Collection 介面不能被例項化,並且在實際的程式設計過程中幾乎不會使用它進行資料的儲存。

Map介面結構

  Map 介面實現的是鍵值對的儲存,類似 python 中的 dict。

  Map中比較常見的是 HashMap、TreeMap、Hashtable 類。

 

Set介面

  Set 介面繼承自 Collection 介面,Collection 介面有的方法 Set 介面中也有。

  Set 介面自身的特性:

    • 不允許重複元素
    • 不區分先後順序(無序)
    • 允許值是 null

  Set 介面有兩個比較常用的具體實現,HashSet、TreeSet。下面分別說一下這兩個集合類。

HashSet

  主要特點是快速查詢元素。HashSet 是基於 Hash 演算法來實現的,在每次新增新的物件的時候,會根據雜湊碼來判斷物件是否重複,雜湊碼的獲取是通過 Object 的 hashCode() 來實現的。同樣 HashSet 也是無序的。

 1 import java.util.*;
 2 /**
 3  * @author jyroy
 4  * HashSet使用
 5  */
 6 public class HashSetDemo {
 7     public static void main(String[] args) {
 8         HashSet hashSet = new HashSet();
 9         hashSet.add("Tom");
10         hashSet.add("Jack");
11         hashSet.add("Roy");
12         System.out.println(hashSet);
13     }
14 }

  當有重複元素新增時,結果如下

 1 import java.util.*;
 2 /**
 3  * @author jyroy
 4  * HashSet使用
 5  */
 6 public class HashSetDemo {
 7     public static void main(String[] args) {
 8         HashSet hashSet = new HashSet();
 9         hashSet.add("Tom");
10         hashSet.add("Tom");
11         hashSet.add("Jack");
12         hashSet.add("Roy");
13         System.out.println(hashSet);
14     }
15 }

 

TreeSet

  主要特點是會進行自然排序,同樣不能重複。參考如下的程式碼,可以看出 TreeSet 把原本無序的值進行了重新排序,依據的就是自然排序。

 1 import java.util.*;
 2 public class TreeSetDemo {
 3     public static void main(String[] args) {
 4         TreeSet treeSet = new TreeSet();
 5         treeSet.add("Tom");
 6         treeSet.add("Jack");
 7         treeSet.add("Roy");
 8         System.out.println(treeSet);
 9     }
10 }

 

  然而,在實際開發中很多時候我們很多時候遵循的不是自然排序,而是有自己定義的排序規則,我們要做的就是新建一個類並且實現 compareTo() 方法。

  下面的程式碼實現的是根據年齡由小到大進行排序,比較簡單,一看就懂的程式碼。

 1 import java.util.TreeSet;
 2 class Person implements Comparable{
 3     public String name;
 4     public int age;
 5     @Override
 6     public String toString() {
 7         return "Person [name=" + name + ", age=" + age + "]";
 8     }
 9     @Override
10     public int compareTo(Object o) {
11         Person person = (Person) o;
12         if(this.age < person.age) {
13             return -1;
14         }else if(this.age > person.age) {
15             return 1;
16         }else {
17             return 0;
18         }
19     }
20 }
21 public class TreeSetDemoCompareto {
22     public static void main(String[] args) {
23         TreeSet treeSet = new TreeSet();
24         Person person1 = new Person();
25         Person person2 = new Person();
26         Person person3 = new Person();
27         person1.name = "Tom";
28         person1.age = 20;
29         person2.name = "Jack";
30         person2.age = 21;
31         person3.name = "Roy";
32         person3.age = 22;
33         treeSet.add(person1);
34         treeSet.add(person2);
35         treeSet.add(person3);
36         System.out.println(treeSet);
37     }
38 }

 

List介面

  List 介面繼承了 Collection 介面,Collection 介面有的方法 List 中也有。

  List 介面自身的特性:

    • 利用陣列方式提供了獲取、修改、刪除的功能。
    • 可以通過方法來獲取元素的位置。
    • 允許重複元素的有序集合。

  List 介面有兩個比較常用的具體實現,ArrayList、Vector、LinkedList。下面分別說一下這兩個集合類。

ArrayList

  ArrayList 本身是通過陣列的方式實現的,大小可以隨著物件的增加而增加。查詢效率比較高,增加、刪除的效率比較低,這也是陣列的一種特性。非執行緒安全的。而且是有序的。

 1 import java.util.*;
 2 /**
 3  * @author jyroy
 4  */
 5 public class ArrayListDemo {
 6     public static void main(String[] args) {
 7         List arrayList = new ArrayList();
 8         arrayList.add("Tom");
 9         arrayList.add("Jack");
10         arrayList.add("Roy");
11         System.out.println(arrayList);
12     }
13 }

 

Vector

  Vector 和 ArrayList 是相似的,都是通過陣列來實現的。

  最大的區別就是執行緒安全方面。Vector 是執行緒安全的,同步的,Vector類對集合的元素操作時都加了synchronized,保證執行緒安全。而 ArrayList 是非執行緒安全的。也是因為執行緒安全的問題,ArrayList 的查詢效率比 Vector 要高。

  另外一個區別是在擴容方面,Vector預設擴容是增長一倍的容量,Arraylist是增長50%+1的容量。

  Vector與ArrayList的remove,add(index,obj)方法都會導致內部陣列進行資料拷貝的操作,這樣在大資料量時,可能會影響效率。

 1 import java.util.*;
 2 public class VectorDemo {
 3     public static void main(String[] args) {
 4         List vectorList = new Vector();
 5         vectorList.add("Roy");
 6         vectorList.add("Tom");
 7         vectorList.add("Jack");
 8         System.out.println(vectorList);
 9     }
10 }

 

LinkedList

  LinkedList 和 ArrayList、Vector相比,在方法的使用上都是相似的。

  LinkedList 是基於雙向連結串列的,比較利於物件的增加和刪除操作,但是對查詢的支援不夠好,這是連結串列的特點。 LinkedList 同樣是執行緒不安全的。

 1 import java.util.*;
 2 public class LinkedListDemo {
 3     public static void main(String[] args) {
 4         List linkedList = new LinkedList();
 5         linkedList.add("Roy");
 6         linkedList.add("Jack");
 7         linkedList.remove(0);
 8         linkedList.add("Tom");
 9         System.out.println(linkedList);
10     }
11 }

 

Queue介面

  Queue 是 Collection 的子介面,中文稱為佇列,特性就是先進先出,先進入佇列的物件,在進行刪除的時候最先被刪除。所有的刪除操作都是在隊首進行的,所有的插入操作都是在隊尾進行的。

 1 import java.util.*;
 2 public class QueueDemo {
 3     public static void main(String[] args) {
 4         Queue queue = new LinkedList();
 5         queue.add("Tom");
 6         queue.add("Roy");
 7         System.out.println(queue.poll());  //出佇列操作
 8         queue.add("Jack");
 9         System.out.println(queue);
10     }
11 }

 

HashMap

  HashMap 是基於雜湊表的 Map 介面的實現類,執行緒不安全。

  雜湊表是通過關鍵碼值(Key value)而直接進行訪問的資料結構。它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。

  下面的程式碼實現了獲取key為 2 的元素的 value。

 1 import java.util.*;
 2 public class HashMapDemo {
 3     public static void main(String[] args) {
 4         HashMap hashMap = new HashMap();
 5         hashMap.put(1, "Tom");
 6         hashMap.put(2, "Jack");
 7         hashMap.put(3, "Roy");
 8         System.out.println(hashMap.get(2));
 9         System.out.println(hashMap);
10     }
11 }

 

TreeMap

  TreeMap 是根據紅黑樹演算法實現的,TreeMap最大的特性就是支援自然排序。從下面的程式碼中也可以非常清晰的看出 TreeMap 利用 key 值進行了自然排序。

  紅黑樹(Red Black Tree) 是一種自平衡二叉查詢樹,是在電腦科學中用到的一種資料結構,典型的用途是實現關聯陣列。

 1 import java.util.*;
 2 public class TreeMapDemo {
 3     public static void main(String[] args) {
 4         TreeMap treeMap = new TreeMap();
 5         treeMap.put("2", "Tom");
 6         treeMap.put("1", "Roy");
 7         treeMap.put("3", "Jack");
 8         System.out.println(treeMap);
 9     }
10 }

HashTable

  HashTable 和 HashMap 是基本一致的。

  最大的區別是 HashTable 是執行緒安全的,HashMap 不是。

 1 import java.util.*;
 2 public class HashTableDemo {
 3     public static void main(String[] args) {
 4         Hashtable hashtable = new Hashtable();
 5         hashtable.put("2", "Tom");
 6         hashtable.put("1", "Roy");
 7         hashtable.put("3", "Jack");
 8         System.out.println(hashtable);
 9     }
10 }

 

 

常見問題

  這些問題是在其他一些大佬的部落格中看到,做了一個整理,都是 Java 集合類的問題。

  1. ArrayList和LinkedList的特點和區別?

  ArrayList: 底層用陣列實現,由於陣列可以通過下標直接訪問指定索引的元素,因此,ArrayList通過索引查詢元素非常快。但由於插入和刪除元素時都會進行陣列的重新排列,因此,ArrayList的插入和刪除操作比較慢。

  LinkedList:底層用連結串列實現,由於連結串列沒有具體的下標,因此,訪問某個索引的節點時需要遍歷該節點前面的所有元素,速度比較慢。由於插入和刪除元素時只需要更新相應元素的指標(或引用),不用重新排列元素,因此,LinkedList對插入和刪除操作比較快。

  LinkedList 比 ArrayList消耗更多的記憶體,因為 LinkedList 中的每個節點儲存了前後節點的引用。


  
2. ArrayList和Vector的區別?  

  ArrayList非執行緒安全,Vector執行緒安全。在擴容時,ArrayList預設擴容當前容量的50%,但Vector預設擴容當前容量的100%。

 

  3. HashSet和TreeSet的區別? 

  HashSet基於HashMap,用鍵來存放HashSet的值,由於HashMap的鍵不能重複,因此,HashSet的值也不會重複,這是集合的一個特點。
  TreeSet基於TreeMap,也是用鍵來存放TreeSet的值。TreeMap的底層實現是紅黑樹,其根據鍵排序,可以得到排好序的資料。

  4. HashMap和HashTable的區別?

  HashMap非執行緒安全,HashTable執行緒安全。
  HashMap可以允許一個null鍵和多個null值,但HashTable不允許,會出現NullPointerException。

 

  5. HashMap和TreeMap的區別?

  HashMap中存放的鍵是隨機的,具有較快的訪問和存取速度,TreeMap中的鍵是按照自然排序排好的。

 

  6. Java集合框架的基礎介面有哪些?

  Collection 和 Map ,一個元素集合,一個是鍵值對集合; 其中 List、Set、Queue 介面繼承了 Collection 介面,一個是有序元素集合,一個是無序元素集合,一個是佇列; 而 ArrayList 和 LinkedList 實現了 List 介面,HashSet 實現了 Set 介面,這幾個都比較常用; HashMap、HashTable、TreeMap 實現了 Map 介面,並且 HashTable 是執行緒安全的,HashMap 是非執行緒安全的,但是 HashMap 效能更好。

  

  7. 如何決定選用HashMap還是TreeMap?

  對於在Map中插入、刪除和定位元素這類操作,HashMap是最好的選擇。然而,假如你需要對一個有序的key集合進行遍歷,TreeMap是更好的選擇。

  

  8. 哪些集合類提供對元素的隨機訪問?

  ArrayList、HashMap、TreeMap和HashTable類提供對元素的隨機訪問。

 

  9. Array和ArrayList有何區別?什麼時候更適合用Array?

  Array可以容納基本型別和物件,而ArrayList只能容納物件。

  Array是指定大小的,而ArrayList大小是根據內容自動擴張的。

  Array沒有提供ArrayList那麼多功能,比如addAll、removeAll和iterator等。儘管ArrayList明顯是更好的選擇,但也有些時候Array比較好用。

  (1)如果列表的大小已經指定,大部分情況下是儲存和遍歷它們。

  (2)對於遍歷基本資料型別,儘管Collections使用自動裝箱來減輕編碼任務,在指定大小的基本型別的列表上工作也會變得很慢。

  (3)如果你要使用多維陣列,使用[][]比List<List<>>更容易。

相關文章