基礎——集合

一、集合和數組的區別

1. 數組:

(1) 長度不可變
(2) 可以是任意類型

2. 集合

(2) 長度可變
(3) 引用類型

二、集合的關係結構

在這裏插入圖片描述
列出了最常使用的集合接口和實現類的關係。

三、java.util.Collection:接口

單列集合的根接口,裏面定義的方法,子接口和實現類都有。

常用方法

  1. public boolean add(E e) : 把給定的對象添加到當前集合中 。
  2. public boolean contains(Object obj) : 判斷當前集合中是否包含給定的對象。
  3. public boolean isEmpty() : 判斷當前集合是否爲空。
  4. public int size() : 返回集合中元素的個數。
  5. public boolean remove(E e) : 把給定的對象在當前集合中刪除。
  6. public Object[] toArray() : 把集合中的元素,存儲到數組中
  7. public void clear() :清空集合中所有的元素。
  • 注意事項:
  1. Collection中沒有定義索引,因爲List有索引,而Set是沒有索引的,索引僅僅是List接口的特性。
  2. toArray方法返回的是Object數組,需要強制類型轉換調用子類特有方法
    解決:使用迭代的方法
  • 並不是所有的集合都有索引,以前使用for+get方法索引,沒了索引就不行了。jdk提供了一中遍歷集合的通用方式那就是使用迭代器java.util.Iterator<E>

    tip: 詳細方法使用和其他方法詳見API文檔學習。

四、java.util.List:接口

繼承自java.util.Collection接口

1、特點

  1. 保證存入元素一次進來的順序
  2. 有索引,實現類可以通過成員方法get(int index)訪問指定位置的元素
  3. 存入的元素可重複

2、常用方法

List繼承了Collection集合的全部方法,同時還有自己的特有方法

  • 特有方法:
  1. public void add(int index, E element) : 將指定的元素,添加到該集合中的指定位置上。
  2. public E get(int index) :返回集合中指定位置的元素。
  3. public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
  4. public E set(int index, E element) :用指定元素替換集合中指定位置的元素,返回值的更新前的元素

3、實現類

1、java.util.ArrayList

(1)底層原理
  1. 底層是數組實現
    a.每次先開闢一個定長爲10的數組空間
    b.如果空間不夠,在開闢一個1.5倍原本長度+1的數組空間,c.把當前數組拷貝進去,最後銷燬原本的數組
    d.並且讓集合對象指向新的數組。

  2. 刪除元素的原理
    a.查找元素是否存在
    b.存在,記錄索引
    c.創建一個新數組
    d.把剩餘元素拷貝進入新數組
    e.數組變量指向新的數組地址
    f.銷燬老數組所佔的內存空間

(2)特點
  1. 查詢速度快,增刪快
  2. 底層是數組結構
  3. 查詢快的原因:有索引,元素內存分佈連續
  4. 線程不同步–不安全–效率高
(3)拓展瞭解
`java.util.Vector<E>:`(基本已經不用)
	1.底層也是數組結構
	2.線程同步--安全--但是效率低下

2、java.util.LinkedList

(1)特點

  1. 查詢慢,增刪快
  2. 底層是鏈表結構
  3. 線程不同步–不安全–效率高

(2)特有方法

  1. void addFirst​(E e) 在該列表開頭插入指定的元素。

  2. void addLast​(E e) 將指定的元素追加到此列表的末尾。

  3. E getFirst​() 返回此列表中的第一個元素。

  4. E getLast​() 返回此列表中的最後一個元素。

  5. E removeFirst​() 從此列表中刪除並返回第一個元素。

  6. E removeLast​() 從此列表中刪除並返回最後一個元素。

  7. LinkedList集合中,具有棧結構特點(先進後出)的方法
    public E pop​() 從此列表表示的堆棧中彈出一個元素。
    public void push​(E e) 將元素推送到由此列表表示的堆棧上。

五、 java.util.Set:接口

繼承自java.util.Collection接口

1、特點

  1. 無索引
  2. 集合內元素唯一

2、常用實現類

(1)java.util.HashSet

特點
  1. 無索引
  2. 集合內元素唯一
  3. 不保證存入和取出的順序是一致的
  4. 底層數據結構:哈希表——數組 + 鏈表(節點數>8–紅黑樹)

(2)java.util.LinkedHashSet

特點
  1. 無索引
  2. 集合內元素唯一
  3. 存入和取出是有序的
  4. 底層數據結構:哈希表 + 鏈表
    哈希表:保證數據的唯一(同HashSet)
    鏈表:保證數據是有序的

3、集合內部保證元素唯一性的原理

根本原因:java.lang.Object類中帶有hashCode方法。

hashCode方法

  1. 返回該對象的哈希碼值(int類型)
  2. Object的hashCode方法,根據對象的地址值計算出一個int數字,叫做哈希碼值(哈希地址值
  3. 所以只要new對象,就會產生新的地址,因此哈希值也就不同

注意事項:

  1. 子類不重寫hashCode方法,調用Object類的hashCode方法,根據對象地址值計算哈希值。
  2. 子類根據地址值計算哈希值沒有意義,需要根據內容計算哈希值。
  3. 由於new對象,就會產生新的地址,因此哈希值也就不同,自定義類要實現存入Set集合保證唯一就必須要重寫hashCode方法和equals方法。
  4. 根據String的代碼測試,發現String覆蓋重寫hashCode方法,重寫方式:根據String中每個字符的ASCII碼值通過一個算法進行相加的出哈希值。只要是算法就會存在缺陷。

出現內容不同哈希值相同的情況

System.out.println("重地".hashCode()); // 1179395
System.out.println("通話".hashCode()); // 1179395

總結–根據內容計算哈希值

  1. 哈希值不同內容一定不相同
  2. 哈希值相同,內容可能不相同,因此還需要調用equeals方法進行內容的判斷。

爲什麼需要hashCode方法?

爲了在使用哈希表的時候能減少equals方法的調用,提高效率。

4、hashSet存儲元素的原理(重點!)

(1)哈希表結構圖
在這裏插入圖片描述

(2)HashSet存儲原理流程圖
在這裏插入圖片描述
(3)實例流程圖
在這裏插入圖片描述
注:
【1】加載因子:說明什麼時候數組(table)進行擴容,0.75說明數組(table)的使用比例大於0.75就進行擴容,擴容爲原來的2倍。

總結

Set集合接口所有實現類保證元素唯一:依賴於hashCode方法和equals方法。
存入Set集合的元素要保證唯一必須覆寫hashCode方法和equals方法。

六、List與Set的轉換

  1. List與Set接口的實現類都有方法:boolean addAll​(Collection<? extends E> c)可以實現兩種接口集合的轉換。
  2. List與Set接口的實現類都有構方法:ArrayList​(Collection<? extends E> c)LinkedList​(Collection<? extends E> c)、HashSet​(Collection<? extends E> c)和LinkedHashSet​(Collection<? extends E> c)可以實現兩種接口類型的轉換。

使用場景:

需求一:

要求把List集合中元素去重
1.按順序
2.不按順序

解決方案:

  • 四種方法:
    1、新建一個列表,元素依次加入並使用contains()方法判斷是否已經存在,新數組中不存在就加入,存在就捨棄。
    2、List數據一個個加入到Set
    3、Set直接用addAll(Collection< E> c)
    4、Set構造方法Set(Collection< E> c)

需求二:
要求把Set集合按從小到大排序

分析與解決方案
我們知道Set集合是沒有sort方法的,並且Collections工具類中的sort方法也是支持List接口的實現子類。
由於List的構造方法可以接受的是Collection c 參數,所以也可以把Set轉換成List,之後使用collections工具類排序

七、集合工具類:java.util.Collections

  • 特點
  1. 構造方法私有
  2. 全部是靜態方法
  • 常用方法:
  1. public static void addAll(List<?> list,T ... elements):把元素集合加入到指定集合list
  2. public static void shuffle(List<?> list):打亂集合內元素
  3. pubiic static <T> void sort(List<T> list,comparator<? super T> comp):把指定集合進行排序(可自定義排序)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章