Java語(yǔ)言基礎(chǔ)四(集合篇)

集合的概述

集合的由來(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ì)元素。

image

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();
 
        //   判斷是否有元素可以訪問(wèn)
        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)訪問(wèn),增刪元素不方便。

  • 其中LinkedList類的底層是采用雙向鏈表進(jìn)行數(shù)據(jù)管理的,訪問(wèn)不方便,增刪元素方便??梢哉J(rèn)為ArrayList和LinkedList的方法在邏輯上完全一樣,只是在性能上有一定的差別

  • ArrayList 更適合于訪問(wèn)而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類相比屬于線程安全的類,效率比較低,以后開(kāi)發(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í)。

  • 該集合中元素沒(méi)有先后放入次序,且不允許重復(fù)。

  • 該集合的主要實(shí)現(xiàn)類是:HashSet類 和TreeSet類以及LinkedHashSet類。

  • 其中HashSet類的底層是采用哈希表進(jìn)行數(shù)據(jù)管理的。

  • 其中TreeSet類的底層是采用紅黑樹(shù)進(jìn)行數(shù)據(jù)管理的。

  • 其中LinkedHashSet類與HashSet類的不同之處在于內(nèi)部維護(hù)了一個(gè)雙向鏈表,鏈表中記錄了元素的迭代順序,也就是元素插入集合中的先后順序,因此便于迭代。

注意:該集合的常用方法參考Collection集合。

元素放入HashSet集合的原理:
  • 使用元素調(diào)用hashCode方法獲取對(duì)應(yīng)的哈希碼值,再由某種哈希算法計(jì)算出該元素在數(shù)組中的索引位置。

  • 若該位置沒(méi)有元素,則將該元素直接放入即可。

  • 若該位置有元素,則使用新元素與已有元素依次比較哈希值,若哈希值不相同,則將該元素直接放入。

  • 若新元素與已有元素的哈希值相同,則使用新元素調(diào)用equals方法與已有元素依次比較。

  • 若相等則添加元素失敗,否則將元素直接放入即可。

-- 那么問(wèn)題來(lái)了,為什么要求重寫(xiě)equals方法后要重寫(xiě)hashCode方法呢?
答:當(dāng)兩個(gè)元素調(diào)用equals方法相等時(shí)證明這兩個(gè)元素相同,重寫(xiě)hashCode方法后保證這兩個(gè)元 素得到的哈希碼值相同,由同一個(gè)哈希算法生成的索引位置相同,此時(shí)只需要與該索引位置已有元素比較即可,從而提高效率并避免重復(fù)元素的出現(xiàn)。

TreeSet集合

二叉樹(shù)主要指每個(gè)節(jié)點(diǎn)最多只有兩個(gè)子節(jié)點(diǎn)的樹(shù)形結(jié)構(gòu)。

滿足以下3個(gè)特征的二叉樹(shù)叫做有序二叉樹(shù):

a.左子樹(shù)中的任意節(jié)點(diǎn)元素都小于根節(jié)點(diǎn)元素值;

b.右子樹(shù)中的任意節(jié)點(diǎn)元素都大于根節(jié)點(diǎn)元素值;

c.左子樹(shù)和右子樹(shù)的內(nèi)部也遵守上述規(guī)則;

由于TreeSet集合的底層采用紅黑樹(shù)進(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類的底層是采用紅黑樹(shù)進(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,若沒(méi)有則返回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ù)組中的索引位置。

  • 若該位置沒(méi)有元素,則將該鍵值對(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)化為紅黑樹(shù)存儲(chǔ),該數(shù)值是:8。

MIN_TREEIFY_CAPACITY:桶中的Node被樹(shù)化時(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) 交換指定列表中指定位置的元素
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容