文章目錄
- 一、集合框架類關系分析
- 1、Collection介面
- 1)collection介面
- 2)AbstractCollection抽象類
- 3)SortedSet介面
- 4)AbstractList和AbstractSet
- 5)繼承基類List的類
- 6)繼承基類Set的類
- 2、Map介面
- 二、集合的意義和使用
- 1、意義
- 2、使用
- 1)執行緒安全PK性能高效
- 2)鏈表PK陣列
- 3)重復pk單一
- 4)有序pk無序
- 三、集合與陣列的相互轉化
- 1、陣列轉化成集合
- 2、集合轉換成陣列
- 1)當原陣列長度>Collection中物件個數
- 2)當原陣列長度=Collection中物件個數
- 3)當原陣列長度
一、集合框架類關系分析
下圖轉載自:
https://blog.csdn.net/weixin_43314519/article/details/107473547

查閱過jdk1.8的原始碼確認過,上圖中應有三處錯誤:
1.LinkedHashSet和HashSet之間的關系是繼承,它們之間的線應該是實線
2.SortedSet和SortedMap都是介面,而且TreeSet和TreeMap不直接實作它們,SortedSet和Treeset、SortedMap和TreeMap之間沒有任何直接關系,正確的關系應該是如下圖所示:

下面三張圖來自重慶大學的《java程式設計》



1、Collection介面
1)collection介面
被一個抽象類AbstractCollectionList和三個介面Set、Queue、List所實作,
依賴于Iterator,以便得到遍歷器進行集合的遍歷
Iterator<E> iterator();
被Map所依賴,Map中的value可以被轉化成Collection,使得整個集合框架更加的統一,
Collection<V> values();
2)AbstractCollection抽象類
實作Collection介面,被AbstractList和AbstractSet所繼承,
3)SortedSet介面
實作了Set介面,被介面NavigableSet介面繼承,NavigableSet介面被具體類TreeSet所實作,
4)AbstractList和AbstractSet
這兩個抽象類是大部分List和Set具體類的父類,它們繼承了AbstractCollection的同時,為了具有相應的特性(Set、List),也實作了Set和List介面,
5)繼承基類List的類
Vector、ArrayList、AbstractSequentialList
6)繼承基類Set的類
HashSet、TreeSet
2、Map介面
和Collection的框架結構大致統一,所以就不復述了,
二、集合的意義和使用
1、意義
用來存盤和操作物件組,
集合PK陣列1、集合可以擴容,陣列不可,
2、陣列既可以存盤物件又可以存盤基本型別,集合只可以存盤物件,
3、集合可以保存有映射關系的資料,陣列不可,
2、使用
集合框架中有非常多的介面、抽象類、具體類,我們如何去挑選一個具體類或者說我們如何自己建立一個自己的類去實作或者繼承介面、抽象類呢?這時,我們主要是從下面幾個方向去思考這個問題:
1)執行緒安全PK性能高效
Collection中所提供的具體實作類基本都是執行緒不安全的,
執行緒安全的實作類只有:Vector、HashTable,
為什么大部分類都要被設計成執行緒不安全的呢?因為執行緒安全的代價是非常昂貴的,性能會遠不如執行緒不安全!
執行緒不安全的集合類如何轉化成執行緒安全的呢?jdk1.8中有個專門的類來解決這個問題:
java.util.Collections,它內部的方法可以將各種執行緒不安全的集合類轉化成執行緒安全的,如:
Collection c=Collections.synchronizedCollection(c);
我們只需要在多執行緒的時候選擇執行緒安全的集合類就可以了,在其他情況下,為了性能高效我們應該選擇執行緒不安全的實作類,
2)鏈表PK陣列
1、鏈表的增添和洗掉的時間復雜度是O(1),查詢的時間復雜度是O(n)
2、陣列的增添(append)的時間復雜度是O(1),(insert)的時間復雜度是o(n),洗掉是O(n),查詢是O(1),
所以我們在查詢次數多于增刪時,選擇陣列,反之,選擇鏈表,
3)重復pk單一
set集合中,元素都是不重復的,然而在List中元素是可以重復的,Map<Key,Value>中,Key也是不可重復的,
4)有序pk無序
注意:這里所說的有序和無序是指其遍歷的順序是否與進入集合的順序一致,
Set為無序,List為有序,如下圖

HashSet、LinkedHashSet、TreeSet之間的比較
HashSet是無序的,TreeSet中為自然順序(從小到大),LinkedHashSet中FIFO(先進先出)
ArrayList、LinkedList、Vector都是先進先出的有序集合(與自然順序無關,除非用了比較器Comparator)
補充:如何讓集合中的資料按照你所期待的方式排序呢?
對某個集合類使用Comparator比較器,或讓加入的類實作Comparable介面即可,
說明:o1-o2>0或者this-o>0return 1為從小到大,return -1為從大到小
注:用比較器實作排序:
1.集合工具類Collections中Collections.sort()方法`
注意:只有List才可以被sort
2.集合類本身的sort方法,
(有些集合類不能被排序,例如hashset)
三、集合與陣列的相互轉化
1、陣列轉化成集合
使用Arrays.asList()
思考:為什么沒有asMap()和asSet()陣列不存在映射關系,所以沒有asMap(),陣列中的數是可以重復的,所以沒有asSet()
下面是代碼演示:從原始碼 public static <T> List<T> asList(T... a)我們發現,aslist的引數為泛型的變長引數,我們都知道,基本資料型別是不可泛型化的,那么為什么int陣列也可以被加入其中呢?因為是以int []的形式加入的,

該方法原始碼如下:
易錯值得注意的是,該方法中回傳的ArrayList并不是java.util.ArrayList,而是Arrays中的內部類!!

思考:為什么不直接回傳java.util.ArrayList呢?如果直接回傳java.util.ArrayList,那么就必須得在該類中增加相應的建構式(如下源代碼),還有一些其他相應的方法,顯然不符合開閉原則:
一個軟體物體如類,模塊和函式應該對修改關閉,對擴展開放
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
經過了上面的介紹,當我們遇見下面的例外時就能很快反應出原因了:

這是因為在Arrays中的ArrayList中并沒有覆寫其父類AbstractList的如下add()方法:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
那么,我們如何正確add呢,顯然,我們需要把它轉化成java.util下的List實作類,在這里以LinkedList為例:

2、集合轉換成陣列
Collection.toArray()
集合轉化成陣列顯然會考慮到陣列長度的問題,嘗試了原陣列長度大于、小于、等于的情況,發現無論哪種情況原陣列的長度最終總會與Collection中物件的個數相等,這是jvm保證的,陣列之間的賦值是會直接傳遞參考,如下圖程式正是說明這一點:d賦值給c,最終c、d都指向同一地址,c==d=true,e即使與d的值相等,但是它們兩個所指向的記憶體空間不同,所以e==d=fals,

1)當原陣列長度>Collection中物件個數

2)當原陣列長度=Collection中物件個數

3)當原陣列長度<Collection中物件個數

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264826.html
標籤:java
