集合的概述
集合的由來(lái)
在介紹集合之前虽惭,應(yīng)先了解java中對(duì)于不同的數(shù)據(jù)類型應(yīng)該用什么來(lái)記錄。
當(dāng)需要在Java程序中記錄單個(gè)數(shù)據(jù)內(nèi)容時(shí)蛇尚,則聲明一個(gè)變量芽唇。
當(dāng)需要在Java程序中記錄多個(gè)類型相同的數(shù)據(jù)內(nèi)容時(shí),聲明一個(gè)一維數(shù)組佣蓉。
當(dāng)需要在Java程序中記錄多個(gè)類型不同的數(shù)據(jù)內(nèi)容時(shí),則創(chuàng)建一個(gè)對(duì)象亲雪。
當(dāng)需要在Java程序中記錄多個(gè)類型相同的對(duì)象數(shù)據(jù)時(shí)勇凭,創(chuàng)建一個(gè)對(duì)象數(shù)組。
當(dāng)需要在Java程序中記錄多個(gè)類型不同的對(duì)象數(shù)據(jù)時(shí)义辕,則準(zhǔn)備一個(gè)集合虾标。
集合的框架結(jié)構(gòu)**
Java中集合框架頂層框架是:java.util.Collection集合 和 java.util.Map集合。
其中Collection集合中存取元素的基本單位是:?jiǎn)蝹€(gè)元素灌砖。
其中Map集合中存取元素的基本單位是:?jiǎn)螌?duì)元素璧函。
Collection集合
概念
Collection接口它是List接口、Queue 接口以及Set接口的父接口基显,因此該接口里定義的方法既可用于操作List集合蘸吓,也可用于操作Queue集合和Set集合。
注意:Collections類是一個(gè)工具類库继,該類主要提供操作集合的一些方法。
Collection接口中常用的方法:
方法聲明 | 功能介紹 |
---|---|
boolean add(E e) | 向集合中添加對(duì)象(單個(gè)元素)窜醉; |
boolean addAll(Collection<? extends E>c) | 用于將參數(shù)指定集合c中的所有元素添加到當(dāng)前集合中(一個(gè)一個(gè)添加)宪萄; |
boolean contains(Object o) | 判斷是否包含指定對(duì)象; |
boolean containsAll(Collection<?> c) | 判斷是否包含參數(shù)指定的所有對(duì)象榨惰; |
boolean retainAll(Collection<?> c) | 保留當(dāng)前集合中存在且參數(shù)集合中存在的所有對(duì)象拜英; |
boolean remove(Object o) | 從集合中刪除對(duì)象(刪除整體對(duì)象); |
boolean removeAll(Collection<?> c) | 從集合中刪除參數(shù)指定的所有對(duì)象(一個(gè)一個(gè)元素刪)琅催; |
void clear() | 清空集合居凶; |
int size() | 返回包含對(duì)象的個(gè)數(shù); |
boolean isEmpty() | 判斷是否為空藤抡; |
boolean equals(Object o) | 判斷是否相等排监; |
int hashCode() | 獲取當(dāng)前集合的哈希碼值; |
Object[] toArray() | 將集合轉(zhuǎn)換為數(shù)組杰捂; |
Iterator iterator() | 獲取當(dāng)前集合的迭代器舆床; |
Iterator接口(迭代器)
基本概念
-- java.util.Iterator接口主要用于描述迭代器對(duì)象,可以遍歷Collection集合中的所有元素。
-- java.util.Collection接口繼承Iterator接口挨队,因此所有實(shí)現(xiàn)Collection接口的實(shí)現(xiàn)類都可以使用該迭代器對(duì)象谷暮。
遍歷集合的方式
public class CollectionTest {
public static void main(String[] args) {
// 準(zhǔn)備一個(gè)Collection集合并放入元素后打印
Collection c1 = new ArrayList();
c1.add("one");
c1.add(2);
c1.add(new Person("zhangsan", 30));//要先封裝一個(gè)Person類
// 遍歷方式一: 自動(dòng)調(diào)用toString方法 String類型的整體
System.out.println("c1 = " + c1); // [one, 2, Person{name='zhangsan', age=30}]
System.out.println("------------------------------------------------");
// 遍歷方式二:使用迭代器來(lái)遍歷集合中的所有元素 更加靈活
// 獲取當(dāng)前集合中的迭代器對(duì)象
Iterator iterator1 = c1.iterator();
// 判斷是否有元素可以訪問
while (iterator1.hasNext()) {
// 取出一個(gè)元素并指向下一個(gè)
System.out.println("獲取到的元素是:" + iterator1.next());
}
/**
遍歷方式三: 使用for each結(jié)構(gòu)實(shí)現(xiàn)集合和數(shù)組中元素的遍歷 代碼簡(jiǎn)單且方法靈活
格式:for(元素類型 變量名 : 數(shù)組/集合名稱) {
循環(huán)體;
}
該方式其實(shí)是迭代器的簡(jiǎn)化版
*/
for (Object obj : c1) {
System.out.println("取出來(lái)的元素是:" + obj);
}
}
}
那如何在遍歷的過(guò)程中進(jìn)行元素的刪除呢?
-- 可以用到迭代器提供的remove()方法
// 借助上面代碼中的集合c1來(lái)實(shí)現(xiàn)
// 3.不斷地去獲取集合中的元素并判斷盛垦,當(dāng)元素值為"one"時(shí)則刪除該元素
iterator1 = c1.iterator(); //重置迭代器
while (iterator1.hasNext()) {
Object obj = iterator1.next();
if("one".equals(obj)) {
iterator1.remove(); //使用迭代器的remove方法刪除元素
ConcurrentModificationException并發(fā)修改異常
}
}
System.out.println("刪除后集合中的元素有:" + c1); // [2, Person{name='zhangsan', age=30}]
List集合
java.util.List集合是Collection集合的子集合湿弦,該集合中允許有重復(fù)的元素并且有先后放入次序。
該集合的主要實(shí)現(xiàn)類有:ArrayList類腾夯、LinkedList類颊埃、Stack類、Vector類蝶俱。
其中ArrayList類的底層是采用動(dòng)態(tài)數(shù)組進(jìn)行數(shù)據(jù)管理的班利,支持下標(biāo)訪問,增刪元素不方便榨呆。
其中LinkedList類的底層是采用雙向鏈表進(jìn)行數(shù)據(jù)管理的罗标,訪問不方便,增刪元素方便积蜻〈掣睿可以認(rèn)為ArrayList和LinkedList的方法在邏輯上完全一樣,只是在性能上有一定的差別
ArrayList 更適合于訪問而LinkedList更適合于插入和刪除竿拆;在性能要求不是特別苛刻的情 形下可以忽略這個(gè)差別宙拉。
其中Stack類的底層是采用動(dòng)態(tài)數(shù)組進(jìn)行數(shù)據(jù)管理的,該類主要用于描述一種具有后進(jìn)先 出特征的數(shù)據(jù)結(jié)構(gòu)丙笋,叫做棧(last in first out LIFO)鼓黔。
其中Vector類的底層是采用動(dòng)態(tài)數(shù)組進(jìn)行數(shù)據(jù)管理的,該類與ArrayList類相比屬于線程安全的類不见,效率比較低澳化,以后開發(fā)中基本不用。
常用的方法:
方法聲明 | 功能介紹 |
---|---|
void add(int index, E element) | 向集合中指定位置添加元素 |
boolean addAll(int index, Collection<? extends E> c) | 向集合中添加所有元素 |
E get(int index) | 從集合中獲取指定位置元素 |
int indexOf(Object o) | 查找參數(shù)指定的對(duì)象 |
int lastIndexOf(Object o) | 反向查找參數(shù)指定的對(duì)象 |
E set(int index, E element) | 修改指定位置的元素 |
E remove(int index) | 刪除指定位置的元素 |
List subList(int fromIndex, int toIndex) | 用于獲取子List(子集合和當(dāng)前集合共用同一塊內(nèi)存空間) |
注意:使用工具類Arrays.asList()可以將數(shù)組轉(zhuǎn)換成集合稳吮,返回的對(duì)象是一個(gè)Arrays內(nèi)部類缎谷,使用該方法時(shí)注意不能使用修改集合的相關(guān)方法否則會(huì)拋出異常。Arrays.asList體現(xiàn)的是適配器模式灶似,只是轉(zhuǎn)換接口列林,后臺(tái)的數(shù)據(jù)依然是數(shù)組。
Queue集合
java.util.Queue集合是Collection集合的子集合酪惭,與List集合屬于平級(jí)關(guān)系希痴。
- 該集合的主要用于描述具有先進(jìn)先出特征的數(shù)據(jù)結(jié)構(gòu),叫做隊(duì)列(first in first out FIFO)春感。
- 該集合的主要實(shí)現(xiàn)類是LinkedList類砌创,因?yàn)樵擃愒谠鰟h方面比較有優(yōu)勢(shì)虏缸。
常用的方法:
方法聲明 | 功能介紹 |
---|---|
boolean offer(E e) | 將一個(gè)對(duì)象添加至隊(duì)尾,若添加成功則返回true |
E poll() | 從隊(duì)首刪除并返回一個(gè)元素 |
E peek() | 返回隊(duì)首的元素(但并不刪除) |
Set集合
java.util.Set集合是Collection集合的子集合嫩实,與List集合平級(jí)刽辙。
該集合中元素沒有先后放入次序,且不允許重復(fù)甲献。
該集合的主要實(shí)現(xiàn)類是:HashSet類 和TreeSet類以及LinkedHashSet類宰缤。
其中HashSet類的底層是采用哈希表進(jìn)行數(shù)據(jù)管理的。
其中TreeSet類的底層是采用紅黑樹進(jìn)行數(shù)據(jù)管理的晃洒。
其中LinkedHashSet類與HashSet類的不同之處在于內(nèi)部維護(hù)了一個(gè)雙向鏈表慨灭,鏈表中記錄了元素的迭代順序,也就是元素插入集合中的先后順序球及,因此便于迭代氧骤。
注意:該集合的常用方法參考Collection集合。
元素放入HashSet集合的原理:
使用元素調(diào)用hashCode方法獲取對(duì)應(yīng)的哈希碼值桶略,再由某種哈希算法計(jì)算出該元素在數(shù)組中的索引位置语淘。
若該位置沒有元素诲宇,則將該元素直接放入即可际歼。
若該位置有元素,則使用新元素與已有元素依次比較哈希值姑蓝,若哈希值不相同鹅心,則將該元素直接放入。
若新元素與已有元素的哈希值相同纺荧,則使用新元素調(diào)用equals方法與已有元素依次比較旭愧。
若相等則添加元素失敗,否則將元素直接放入即可宙暇。
-- 那么問題來(lái)了输枯,為什么要求重寫equals方法后要重寫hashCode方法呢?
答:當(dāng)兩個(gè)元素調(diào)用equals方法相等時(shí)證明這兩個(gè)元素相同占贫,重寫hashCode方法后保證這兩個(gè)元 素得到的哈希碼值相同桃熄,由同一個(gè)哈希算法生成的索引位置相同,此時(shí)只需要與該索引位置已有元素比較即可型奥,從而提高效率并避免重復(fù)元素的出現(xiàn)瞳收。
TreeSet集合
二叉樹主要指每個(gè)節(jié)點(diǎn)最多只有兩個(gè)子節(jié)點(diǎn)的樹形結(jié)構(gòu)。
滿足以下3個(gè)特征的二叉樹叫做有序二叉樹:
a.左子樹中的任意節(jié)點(diǎn)元素都小于根節(jié)點(diǎn)元素值厢汹;
b.右子樹中的任意節(jié)點(diǎn)元素都大于根節(jié)點(diǎn)元素值螟深;
c.左子樹和右子樹的內(nèi)部也遵守上述規(guī)則;
由于TreeSet集合的底層采用紅黑樹進(jìn)行數(shù)據(jù)的管理烫葬,當(dāng)有新元素插入到TreeSet集合時(shí)界弧,需要使用新元素與集合中已有的元素依次比較來(lái)確定新元素的合理位置凡蜻。
比較元素大小的規(guī)則有兩種方式:
使用元素的自然排序規(guī)則進(jìn)行比較并排序,讓元素類型實(shí)現(xiàn)java.lang.Comparable接口夹纫;
使用比較器規(guī)則進(jìn)行比較并排序咽瓷,構(gòu)造TreeSet集合時(shí)傳入java.util.Comparator接口;
自然排序的規(guī)則比較單一舰讹,而比較器的規(guī)則比較多元化茅姜,而且比較器優(yōu)先于自然排序;
Map集合
概念
-- java.util.Map<K,V>集合中存取元素的基本單位是:?jiǎn)螌?duì)元素月匣,其中類型參數(shù)如下:
- K - 此映射所維護(hù)的鍵(Key)的類型钻洒,相當(dāng)于目錄。
- V - 映射值(Value)的類型锄开,相當(dāng)于內(nèi)容素标。
該集合中key是不允許重復(fù)的,而且一個(gè)key只能對(duì)應(yīng)一個(gè)value萍悴。
該集合的主要實(shí)現(xiàn)類有:HashMap類头遭、TreeMap類、LinkedHashMap類癣诱、Hashtable類计维、Properties類。
其中HashMap類的底層是采用哈希表進(jìn)行數(shù)據(jù)管理的。
其中TreeMap類的底層是采用紅黑樹進(jìn)行數(shù)據(jù)管理的。
其中LinkedHashMap類與HashMap類的不同之處在于內(nèi)部維護(hù)了一個(gè)雙向鏈表习瑰,鏈表中記錄了元素的迭代順序,也就是元素插入集合中的先后順序欠母,因此便于迭代。
其中Hashtable類是古老的Map實(shí)現(xiàn)類吆寨,與HashMap類相比屬于線程安全的類赏淌,且不允許null作為key或者value的數(shù)值。
其中Properties類是Hashtable類的子類啄清,該對(duì)象用于處理屬性文件六水,key和value都是String類型的。
Map集合是面向查詢優(yōu)化的數(shù)據(jù)結(jié)構(gòu), 在大數(shù)據(jù)量情況下有著優(yōu)良的查詢性能盒延。
經(jīng)常用于根據(jù)key檢索value的業(yè)務(wù)場(chǎng)景缩擂。
常用的方法:
方法聲明 | 功能介紹 |
---|---|
V put(K key, V value) | 將Key-Value對(duì)存入Map,若集合中已經(jīng)包含該Key添寺,則替換該Key所對(duì)應(yīng)的Value胯盯,返回值為該Key原來(lái)所對(duì)應(yīng)的Value,若沒有則返回null; |
V get(Object key) | 返回與參數(shù)Key所對(duì)應(yīng)的Value對(duì)象计露,如果不存在則返回null |
boolean containsKey (Object key) | 判斷集合中是否包含指定的Key |
boolean containsValue (Object value) | 判斷集合中是否包含指定的Value |
V remove(Object key) | 根據(jù)參數(shù)指定的key進(jìn)行刪除 |
Set keySet() | 返回此映射中包含的鍵的Set視圖 |
Collection values() | 返回此映射中包含的值的Set視圖 |
Set<Map.Entry<K,V>>entrySet() | 返回此映射中包含的映射的Set視圖 |
這里就演示添加和遍歷的操作:
// 1.準(zhǔn)備一個(gè)Map集合
Map<String, String> m1 = new HashMap<>();
// 2.向集合中添加元素并打印
String str1 = m1.put("1", "one");
System.out.println("原來(lái)的value數(shù)值為:" + str1); // null
System.out.println("m1 = " + m1); // {1=one}
str1 = m1.put("2", "two");
System.out.println("原來(lái)的value數(shù)值為:" + str1); // null
System.out.println("m1 = " + m1); // {1=one, 2=two}
str1 = m1.put("3", "three");
System.out.println("原來(lái)的value數(shù)值為:" + str1); // null
System.out.println("m1 = " + m1); // {1=one, 2=two, 3=three}
// 實(shí)現(xiàn)了修改的功能
str1 = m1.put("1", "eleven");
System.out.println("原來(lái)的value數(shù)值為:" + str1); // one
System.out.println("m1 = " + m1); // {1=eleven, 2=two, 3=three}
/**
Map集合的三種遍歷方式
*/
// 方式一:獲取Map集合中所有的key并組成Set視圖
Set<String> s1 = m1.keySet();
// 遍歷所有的key
for (String ts : s1) {
System.out.println(ts + "=" + m1.get(ts));
}
// 方式二:獲取Map集合中所有的Value并組成Collection視圖
Collection<String> co = m1.values();
for (String ts : co) {
System.out.println("ts = " + ts);
}
// 方式三:獲取Map集合中所有的鍵值對(duì)并組成Set視圖
Set<Map.Entry<String, String>> entries = m1.entrySet();
for (Map.Entry<String, String> me : entries) {
System.out.println(me);
}
元素放入HashMap集合的原理:
使用元素的key調(diào)用hashCode方法獲取對(duì)應(yīng)的哈希碼值博脑,再由某種哈希算法計(jì)算在數(shù)組中的索引位置憎乙。
若該位置沒有元素,則將該鍵值對(duì)直接放入即可叉趣。
若該位置有元素泞边,則使用key與已有元素依次比較哈希值,若哈希值不相同疗杉,則將該元素直接放入阵谚。
若key與已有元素的哈希值相同,則使用key調(diào)用equals方法與已有元素依次比較烟具。
若相等則將對(duì)應(yīng)的value修改梢什,否則將鍵值對(duì)直接放入即可。
相關(guān)的常量:
DEFAULT_INITIAL_CAPACITY : HashMap的默認(rèn)容量是:16朝聋。
DEFAULT_LOAD_FACTOR:HashMap的默認(rèn)加載因子是:0.75嗡午。
threshold:擴(kuò)容的臨界值,該數(shù)值為:容量*填充因子冀痕,也就是:12荔睹。
TREEIFY_THRESHOLD:若Bucket中鏈表長(zhǎng)度大于該默認(rèn)值則轉(zhuǎn)化為紅黑樹存儲(chǔ),該數(shù)值是:8言蛇。
MIN_TREEIFY_CAPACITY:桶中的Node被樹化時(shí)最小的hash表容量僻他,該數(shù)值是:64。
Collections工具類類
概念
-- java.util.Collections類主要提供了對(duì)集合操作或者返回集合的靜態(tài)方法猜极。
注意:Collection是List和Set的父接口中姜,而Collections是一個(gè)工具類消玄。
常用的方法
方法聲明 | 功能介紹 |
---|---|
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) | 根據(jù)元素的自然順序返回給定集合的最大元素 |
static T max(Collection<? extends T> coll, Comparator<?super T> comp) | 根據(jù)指定比較器引發(fā)的順序返回給定集合的最大元素 |
static <T extends Object & Comparable<?super T>> T min(Collection<? extends T> coll) | 根據(jù)元素的自然順序返回給定集合的最小元素 |
static T min(Collection<? extends T> coll, Comparator<?super T> comp) | 根據(jù)指定比較器引發(fā)的順序返回給定集合的最小元素 |
static void copy(List<? super T> dest, List<? extends T>src) 將一個(gè)列表中的所有元素復(fù)制到另一個(gè)列表中 | |
static void reverse(List<?> list) | 反轉(zhuǎn)指定列表中元素的順序 |
static void shuffle(List<?> list) | 使用默認(rèn)的隨機(jī)源隨機(jī)置換指定的列表 |
static <T extends Comparable<? super T>> void sort(List list) | 根據(jù)其元素的自然順序?qū)⒅付斜戆瓷蚺判?/td> |
static void sort(List list, Comparator<? super T> c) | 根據(jù)指定比較器指定的順序?qū)χ付斜磉M(jìn)行排序 |
static void swap(List<?> list, int i, int j) | 交換指定列表中指定位置的元素 |