Java集合類詳解

Java的集合就像是一種容器,可以把對個對象的引用放入容器中,其中不斷可以存儲不等的多個對象,還可以用於保存具有映射關係的關聯數組。其中Java的集合可以分爲三種體系:

  • Set集合:內部元素無序,並且元素不可以重複;

  • List集合:內部元素有序,且元素可以重複;

  • Map集合:具有映射關係的集合

 

(一)Collection接口:

Collection接口是List,Set和Queue接口的父接口,該接口中定義的方法可以用戶操作List,Set和Queue集合;其中主要有以下的一些方法:

 

這裏給出測試上述部分方法的舉例:

首先給出Person類,用於放入集合中

 View Code

 

 

然後舉例說明Collection接口的相關方法:

 View Code

 

 

(二)Set集合

Set集合不允許包含相同的元素,如果把兩個相同的元素添加進入Set集合,則添加操作失敗。Set集合中判斷兩個對象是否相同不是使用“==” 而是根據equals()方法的返回值決定;

2.1 HashSet

1)HashSet特點

HashSet 是 Set 接口的典型實現,大多數時候使用 Set 集合時都使用這個實現類。
HashSet 按 Hash 算法來存儲集合中的元素,因此具有很好的存取和查找性能。
HashSet 具有以下特點:

  • 不能保證元素的排列順序

  • HashSet 不是線程安全的

  • 集合元素可以使 null

當向 HashSet 集合中存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的 hashCode 值,然後根據 hashCode 值決定該對象在 HashSet 中的存儲位置。如果兩個元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會把它們存儲在不同的位置,但依然可以添加成功。

重寫 hashCode() 方法的基本原則

  1. 在程序運行時,同一個對象多次調用 hashCode() 方法應該返回相同的值

  2. 當兩個對象的 equals() 方法比較返回 true 時,這兩個對象的 hashCode() 方法的返回值也應相等

  3. 對象中用作 equals() 方法比較的 Field,都應該用來計算 hashCode 值

 

 View Code

 

2)子類 LinkedHashSet 

LinkedHashSet 集合根據元素的hashCode值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,這使得元素看起來是以插入順序保存的。
LinkedHashSet 性能插入性能略低於 HashSet,但在迭代訪問 Set 裏的全部元素時有很好的性能。
LinkedHashSet 不允許集合元素重複。

2.2 TreeSet

TreeSet 是 SortedSet 接口的實現類,TreeSet 可以確保集合元素處於排序狀態。

其中TreeSet還有以下的一些常用的操作:這裏就不一一列舉實現了

  • Comparator comparator()

  • Object first()   獲取第一個元素

  • Object last()   獲取最後一個元素

  • Object lower(Object e)    

  • Object higher(Object e)

  • SortedSet subSet(fromElement, toElement)

  • SortedSet headSet(toElement)

  • SortedSet tailSet(fromElement)

TreeSet 支持兩種排序方法:自然排序和定製排序。默認情況下,TreeSet 採用自然排序。

 1)自然排序

排序:TreeSet 會調用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關係,然後將集合元素按升序排列,如果試圖把一個對象添加到 TreeSet 時,則該對象的類必須實現 Comparable 接口。實現 Comparable 的類必須實現 compareTo(Object obj) 方法,兩個對象即通過 compareTo(Object obj) 方法的返回值來比較大小。

實現Compareable接口代碼示例:

複製代碼

 1 package collection; 2  3 /** 4  * Created by : Zhong 5  * DATE : 2017/3/2 6  * Time : 23:06 7  * Funtion : 8  */ 9 public class PersonCompare implements Comparable{10     public String name;11     public int age;12     public PersonCompare() {13     }14     public PersonCompare(String name, int age) {15         this.name = name;16         this.age = age;17     }18     public String getName() {19         return name;20     }21     public void setName(String name) {22         this.name = name;23     }24     public int getAge() {25         return age;26     }27     public void setAge(int age) {28         this.age = age;29     }30     @Override31     public String toString() {32         return "Person{" +33                 "name='" + name + '\'' +34                 ", age=" + age +35                 '}';36     }37 38     @Override39     public boolean equals(Object o) {40         if (this == o) return true;41         if (o == null || getClass() != o.getClass()) return false;42 43         PersonCompare person = (PersonCompare) o;44 45         if (age != person.age) return false;46         return name != null ? name.equals(person.name) : person.name == null;47 48     }49     @Override50     public int hashCode() {51         int result = name != null ? name.hashCode() : 0;52         result = 31 * result + age;53         return result;54     }55 56     @Override
57     public int compareTo(Object o) {
58 
59         if (o instanceof PersonCompare){
60             PersonCompare personCompare = (PersonCompare) o;
61             return this.name.compareTo(personCompare.name);
62         }else{
63             throw new ClassCastException("轉換類型失敗!");
64         }
65     }66 }

複製代碼

 

自然排序方法的使用示例:

 

複製代碼

 1  /** 2      * 自然排序情況 3      * 4      * 默認情況下TreeSet要求集合中的元素必須實現Comparable接口 5      * Comparable接口中只有一個方法: 6      * public int compareTo(T o) 7      *     如果返回0 代表兩個元素相等 8      *     如果返回正數,代表當前元素大 9      *     如果返回負數,代表當前元素小10      * TreeSet 會調用每個元素的compareTo()方法去和集合中的每個已經有的元素比較,進而決定當前元素在集合中的位置11      *12      */13     @Test14     public void testTreeSet(){15 16         TreeSet treeSet = new TreeSet();17         treeSet.add(new PersonCompare("AAA",16));18         treeSet.add(new PersonCompare("BBB",13));19         treeSet.add(new PersonCompare("CCC",11));20         treeSet.add(new PersonCompare("DDD",15));21 22         for (Object o : treeSet) {23             System.out.println(o.toString());24         }25     }

複製代碼

 

 

 

Comparable 的典型實現:

  • BigDecimal、BigInteger 以及所有的數值型對應的包裝類:按它們對應的數值大小進行比較

  • Character:按字符的 UNICODE 值來進行比較

  • Boolean:true 對應的包裝類實例大於 false 對應的包裝類實例

  • String:按字符串中字符的 UNICODE 值進行比較

  • Date、Time:後邊的時間、日期比前面的時間、日期大

 因爲只有相同類的兩個實例纔會比較大小,所以向 TreeSet 中添加的應該是同一個類的對象。當需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與 compareTo(Object obj) 方法有一致的結果:如果兩個對象通過 equals() 方法比較返回 true,則通過 compareTo(Object obj) 方法比較應返回 0

2)定製排序

如果需要實現定製排序,則需要在創建 TreeSet 集合對象時,提供一個 Comparator 接口的實現類對象。由該 Comparator 對象負責集合元素的排序邏輯。定製排序的優點就是讓需要排序的對象不需要實現Compareable接口,減少了耦合性,是程序更加簡單。

 定製排序方法代碼示例:

複製代碼

 1 /** 2      * 定製排序 3      * 4      */ 5     @Test 6     public void testTreeSet2(){ 7         //創建comparator接口的實現類對象 8         Comparator comparator = new Comparator() { 9             @Override10             public int compare(Object o1, Object o2) {11                 if (o1 instanceof Person && o2 instanceof Person){12                     Person p1 = (Person)o1;13                     Person p2 = (Person)o2;14                     return p1.getAge() - p2.getAge();15                 }16                 throw new ClassCastException("類型轉換異常");17             }18         };19 20         //創建TreeSet對象,傳入Comparator接口的實現類對象21         TreeSet treeSet = new TreeSet(comparator);22         treeSet.add(new Person("AAA",16));23         treeSet.add(new Person("BBB",13));24         treeSet.add(new Person("CCC",11));25         treeSet.add(new Person("DDD",15));26 27         for (Object person : treeSet) {28             System.out.println(person.toString());29         }30     }

複製代碼

 

(三)List集合

3.1 概述

  • List 代表一個元素有序、且可重複的集合,集合中的每個元素都有其對應的順序索引

  • List 允許使用重複元素,可以通過索引來訪問指定位置的集合元素。

  • List 默認按元素的添加順序設置元素的索引。

  • List 集合裏添加了一些根據索引來操作集合元素的方法

    • void add(int index, Object ele)  把元素添加到指定的位置  原來的元素被後移

    • boolean addAll(int index, Collection eles) 把一組元素添加到指定的位置

    • Object get(int index)       獲取指定索引的元素

    • int indexOf(Object obj)  獲取指定對象的索引,如果元素不存在,則返回-1

    • int lastIndexOf(Object obj)   獲取重複的元素的最後一個索引

    • Object remove(int index)  移除指定索引的元素

    • Object set(int index, Object ele)  設置指定索引的元素,原來的元素被替換

    • List subList(int fromIndex, int toIndex)

3.2 ArrayList 和 Vector

ArrayList 和 Vector 是 List 接口的兩個典型實現
區別:

  • 是一個古老的集合,通常建議使用 ArrayList

  • ArrayList 是線程不安全的,而 Vector 是線程安全的。

  • 即使爲保證 List 集合線程安全,也不推薦使用 Vector

Arrays.asList(…) 方法返回的 List 集合即不是 ArrayList 實例,也不是 Vector 實例。 Arrays.asList(…) 返回值是一個固定長度的 List 集合。

 

(四)Map集合

4.1 概述

  • Map 用於保存具有映射關係的數據,因此 Map 集合裏保存着兩組值,一組值用於保存 Map 裏的 Key,另外一組用於保存 Map 裏的 Value

  • Map 中的 key 和 value 都可以是任何引用類型的數據

  • Map 中的 Key 不允許重複,即同一個 Map 對象的任何兩個 Key 通過 equals 方法比較中返回 false

  • Key 和 Value 之間存在單向一對一關係,即通過指定的 Key 總能找到唯一的,確定的 Value。

常用方法:

  • void clear()   清空map

  • boolean containsKey(Object key)   檢測是否包含key值

  • boolean containsValue(Object value) 檢測是否包含value值

  • Set<Mao.Entry<K,V>> entrySet()  得到剪枝對對應的Entry 的Set

  • V get(Object key)

  • Set<K> keySet()

  • V put(K key, V value)

  • V remove(Object key) 移除指定key 的鍵值對

4.2 HashMap 和 Hashtable

  • HashMap 和 Hashtable 是 Map 接口的兩個典型實現類

  • 區別:

    • Hashtable 是一個古老的 Map 實現類,不建議使用

    • Hashtable 是一個線程安全的 Map 實現,但 HashMap 是線程不安全的。

    • Hashtable 不允許使用 null 作爲 key 和 value,而 HashMap 可以

  • 與 HashSet 集合不能保證元素的順序的順序一樣,Hashtable 、HashMap 也不能保證其中 key-value 對的順序

  • Hashtable 、HashMap 判斷兩個 Key 相等的標準是:兩個 Key 通過 equals 方法返回 true,hashCode 值也相等。

  • Hashtable 、HashMap 判斷兩個 Value相等的標準是:兩個 Value 通過 equals 方法返回 true

4.3 LinkedHashMap 

LinkedHashMap 是 HashMap 的子類
LinkedHashMap 可以維護 Map 的迭代順序:迭代順序與 Key-Value 對的插入順序一致

複製代碼

 1 @Test 2     public void testLinkedHashMap(){ 3         Map map = new LinkedHashMap<>(); 4  5         map.put("CC", new Person("CC", 18)); 6         map.put("AA", new Person("AA", 10)); 7         map.put("DD", new Person("DD", 12)); 8         map.put("BB", new Person("BB", 16)); 9 10         /*Iterator it = map.keySet().iterator();11         while (it.hasNext()){12             Object key = it.next();13             Object value = map.get(key);14             System.out.println(key+":"+value);15         }16         System.out.println();*/17 18         for (Object key : map.keySet()){19             Object value = map.get(key);20             System.out.println(key+":"+value);21         }22     }

複製代碼

 

4.4 TreeMap

TreeMap 存儲 Key-Value 對時,需要根據 Key 對 key-value 對進行排序。TreeMap 可以保證所有的 Key-Value 對處於有序狀態。
TreeMap 的 Key 的排序:

  • 自然排序:TreeMap 的所有的 Key 必須實現 Comparable 接口,而且所有的 Key 應該是同一個類的對象,否則將會拋出 ClasssCastException

  • 定製排序:創建 TreeMap 時,傳入一個 Comparator 對象,該對象負責對 TreeMap 中的所有 key 進行排序。此時不需要 Map 的 Key 實現 Comparable 接口

 同樣這裏的key值也需要具有可比性

複製代碼

 1    @Test 2     public void testTreeMap(){ 3         Map map = new TreeMap<>(); 4  5         //這裏使用加入Compareable接口的Person類,這樣纔可以進行排序 6         map.put(new PersonCompare("CC", 18),"CC"); 7         map.put(new PersonCompare("AA", 10),"AA"); 8         map.put(new PersonCompare("DD", 12),"DD"); 9         map.put(new PersonCompare("BB", 16),"BB");10 11         for (Object key : map.keySet()){12             Object value = map.get(key);13             System.out.println(key+":"+value);14         }15     }

複製代碼

 

 

(五)操作集合的工具類:Collections

Collections 是一個操作 Set、List 和 Map 等集合的工具類
Collections 中提供了大量方法對集合元素進行排序、查詢和修改等操作,還提供了對集合對象設置不可變、對集合對象實現同步控制等方法

5.1 排序操作:

  • reverse(List):反轉 List 中元素的順序

  • shuffle(List):對 List 集合元素進行隨機排序

  • sort(List):根據元素的自然順序對指定 List 集合元素按升序排序

  • sort(List,Comparator):根據指定的 Comparator 產生的順序對 List 集合元素進行排序

  • swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進行交換

5.2 查找、替換

  • Object max(Collection):根據元素的自然順序,返回給定集合中的最大元素

  • Object max(Collection,Comparator):根據 Comparator 指定的順序,返回給定集合中的最大元素

  • Object min(Collection)

  • Object min(Collection,Comparator)

  • int frequency(Collection,Object):返回指定集合中指定元素的出現次數

  • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對象的所有舊值

5.3 同步控制

Collections 類中提供了多個 synchronizedXxx()方法,該方法可使將指定集合包裝成線程同步的集合,從而可以解決多線程併發訪問集合時的線程安全問題

 代碼示例:

 

複製代碼

 1 package collection; 2  3 import org.junit.Test; 4  5 import java.util.*; 6  7 /** 8  * Created by :Infaraway 9  * DATE : 2017/3/2610  * Time : 16:3911  * Funtion :12  */13 public class CollectionsTest {14 15     @Test16     public void testList(){17         List list = new ArrayList<>();18         list.add(new Person("AAA",16));19         list.add(new Person("BBB",13));20         list.add(new Person("CCC",11));21         list.add(new Person("DDD",15));22 23         for (Object o : list) {24             System.out.println(o.toString());25         }26         //按年齡升序排列27         //實現Comparator類進行排序操作28         Collections.sort(list, new Comparator() {29             @Override30             public int compare(Object o1, Object o2) {31                 if (o1 instanceof Person && o2 instanceof Person){32                     Person p1 = (Person)o1;33                     Person p2 = (Person)o2;34                     return p1.getAge() - p2.getAge();35                 }36                 throw new ClassCastException("類型轉換異常");37             }38         });39 40         System.out.println();41         for (Object o : list) {42             System.out.println(o.toString());43         }44 45 46         //獲取list中最小的元素47         //要求集合中的元素都實現Compareable接口48         Set set = new HashSet();49 50         set.add(new PersonCompare("AAA",20));51         set.add(new PersonCompare("BBB",34));52         set.add(new PersonCompare("CCC",27));53         set.add(new PersonCompare("DDD",29));54 55         for (Object person : set) {56             System.out.println(person.toString());57         }58         System.out.println();59 60         Object object = Collections.min(set);61         System.out.println(object.toString());62     }63 64 }

複製代碼



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章