Kotlin學(xué)習(xí)第 6 課:Kotlin 集合框架:操作數(shù)據(jù)的核心工具

在日常開發(fā)中,我們經(jīng)常需要處理 “一組數(shù)據(jù)”—— 比如學(xué)生列表、商品信息、用戶配置等。Kotlin 的集合框架就是專門用來管理和操作這些 “數(shù)據(jù)組” 的核心工具,它提供了一套簡潔、高效的 API,涵蓋了數(shù)據(jù)的存儲、查詢、過濾、排序等常見需求。本節(jié)課我們將從集合的分類開始,逐步深入講解 List、Set、Map 三大核心集合,以及能大幅簡化代碼的 “高階函數(shù)操作”。

一、集合的分類與初始化:先搞懂 “可變” 與 “不可變”

Kotlin 集合框架的核心特點(diǎn)是區(qū)分 “不可變集合” 和 “可變集合” —— 這是為了滿足 “數(shù)據(jù)安全性” 需求(比如避免誤修改全局?jǐn)?shù)據(jù))。兩者的本質(zhì)區(qū)別是:不可變集合創(chuàng)建后無法修改(不能添加、刪除元素),可變集合支持動態(tài)修改。

1. 三大集合類型的分類

Kotlin 主要提供三種核心集合類型,每種類型都對應(yīng) “不可變” 和 “可變” 兩個版本:

集合類型 不可變版本(只讀) 可變版本(可讀寫) 核心特性
列表 List MutableList 有序、可重復(fù)元素
集合 Set MutableSet 無序、不可重復(fù)元素
映射 Map MutableMap 鍵值對(key-value)、鍵唯一

2. 集合的創(chuàng)建方式:一行代碼搞定

Kotlin 提供了專門的 “工廠函數(shù)” 來創(chuàng)建集合,無需手動 new,語法簡潔。

(1)List 的創(chuàng)建

  • 不可變 List:用 listOf() 函數(shù),創(chuàng)建后無法修改;
  • 可變 List:用 mutableListOf() 函數(shù),支持 add/remove 等操作;
  • 若需指定初始容量(優(yōu)化性能):用 mutableListOf(capacity)(比如 mutableListOf(10) 表示初始容量為 10)。

示例:

// 1. 不可變 List:元素按插入順序保存,可重復(fù)
val fruitList: List<String> = listOf("蘋果", "香蕉", "蘋果", "橙子")
// fruitList.add("葡萄") // 報錯:不可變集合沒有 add 方法

// 2. 可變 List:可動態(tài)修改
val mutableFruitList: MutableList<String> = mutableListOf("蘋果", "香蕉")
mutableFruitList.add("葡萄") // 添加元素
mutableFruitList.remove("香蕉") // 刪除元素
println(mutableFruitList) // 輸出:[蘋果, 葡萄]

// 3. 創(chuàng)建空 List(不可變空集合用 emptyList(),可變空集合用 mutableListOf())
val emptyImmutableList: List<Int> = emptyList()
val emptyMutableList: MutableList<Int> = mutableListOf()

(2)Set 的創(chuàng)建

  • 不可變 Set:用 setOf() 函數(shù),自動去重、無序;
  • 可變 Set:用 mutableSetOf() 函數(shù),支持修改;
  • 若需 “有序 Set”(按插入順序保存):用 LinkedHashSet(創(chuàng)建方式 linkedSetOf())。

示例:

// 1. 不可變 Set:重復(fù)元素被自動忽略,無序(輸出順序可能和插入順序不同)
val colorSet: Set<String> = setOf("紅色", "綠色", "紅色", "藍(lán)色")
println(colorSet) // 輸出:[紅色, 綠色, 藍(lán)色](去重)

// 2. 可變 Set:支持添加/刪除
val mutableColorSet: MutableSet<String> = mutableSetOf("紅色", "綠色")
mutableColorSet.add("黃色")
mutableColorSet.remove("紅色")
println(mutableColorSet) // 輸出:[綠色, 黃色](無序)

// 3. 有序 Set(LinkedHashSet):按插入順序保存,仍去重
val linkedColorSet: MutableSet<String> = linkedSetOf("紅色", "綠色", "紅色")
println(linkedColorSet) // 輸出:[紅色, 綠色](有序+去重)

(3)Map 的創(chuàng)建

Map 是 “鍵值對” 集合,每個元素包含 key(鍵)和 value(值),核心規(guī)則是 “鍵唯一,值可重復(fù)”。

  • 不可變 Map:用 mapOf() 函數(shù),鍵值對用 to 關(guān)鍵字連接(如 key to value);
  • 可變 Map:用 mutableMapOf() 函數(shù),支持 put/remove 等操作;
  • 有序 Map(按插入順序):用 linkedMapOf() 函數(shù)。

示例:

// 1. 不可變 Map:鍵唯一,重復(fù)鍵會覆蓋(后面的覆蓋前面的)
val userMap: Map<String, Any> = mapOf(
    "name" to "張三",
    "age" to 20,
    "gender" to "男",
    "age" to 21 // 重復(fù)鍵,覆蓋前面的 20
)
println(userMap) // 輸出:{name=張三, age=21, gender=男}

// 2. 可變 Map:支持添加/修改/刪除
val mutableUserMap: MutableMap<String, Any> = mutableMapOf(
    "name" to "李四",
    "age" to 18
)
mutableUserMap.put("gender", "女") // 添加鍵值對
mutableUserMap["age"] = 19 // 簡化寫法:修改值(等價于 put)
mutableUserMap.remove("gender") // 刪除鍵值對
println(mutableUserMap) // 輸出:{name=李四, age=19}

// 3. 有序 Map(LinkedHashMap):按插入順序保存鍵值對
val linkedUserMap: MutableMap<String, Any> = linkedMapOf(
    "name" to "王五",
    "age" to 22
)
println(linkedUserMap) // 輸出:{name=王五, age=22}(順序與插入一致)


二、List 集合:有序、可重復(fù)的 “數(shù)據(jù)隊列”

List 是最常用的集合類型,核心特性是元素有序(有固定索引,從 0 開始)、可重復(fù),適合存儲 “需要按順序訪問” 的數(shù)據(jù)(比如排行榜、待辦清單)。

1. List 的核心特性回顧

  • 有序:每個元素有唯一索引,可通過索引快速獲取元素;
  • 可重復(fù):同一元素可多次添加,索引不同則視為不同位置的元素;
  • 不可變 List(List):僅支持查詢,無修改方法;
  • 可變 List(MutableList):支持添加、刪除、修改元素。

2. List 的常用操作(附代碼示例)

(1)獲取元素:通過索引

不可變和可變 List 都支持,用 get(index) 方法或簡化的 [index] 運(yùn)算符(推薦后者,更簡潔)。

val fruitList = listOf("蘋果", "香蕉", "橙子")
// 方式1:get(index)
val firstFruit = fruitList.get(0)
// 方式2:[index](簡化寫法,推薦)
val secondFruit = fruitList[1]
println("第一個水果:$firstFruit,第二個水果:$secondFruit") 
// 輸出:第一個水果:蘋果,第二個水果:香蕉

// 注意:索引越界會報錯(比如訪問 index=3,集合長度為 3,索引最大為 2)
// fruitList[3] // 拋出 IndexOutOfBoundsException

(2)添加元素:僅可變 List 支持

add(element) 追加到末尾,或 add(index, element) 插入到指定索引位置。

val mutableFruitList = mutableListOf("蘋果", "香蕉")
// 1. 追加到末尾
mutableFruitList.add("葡萄") 
// 2. 插入到索引 1 的位置(原索引 1 及之后的元素后移)
mutableFruitList.add(1, "橙子") 
println(mutableFruitList) // 輸出:[蘋果, 橙子, 香蕉, 葡萄]

(3)刪除元素:僅可變 List 支持

  • remove(element):根據(jù)元素值刪除(刪除第一個匹配的元素);
  • removeAt(index):根據(jù)索引刪除(更高效,直接定位);
  • clear():清空所有元素。
val mutableFruitList = mutableListOf("蘋果", "橙子", "香蕉", "葡萄")
// 1. 根據(jù)元素值刪除
mutableFruitList.remove("橙子") 
// 2. 根據(jù)索引刪除(刪除第三個元素,索引 2)
mutableFruitList.removeAt(2) 
println(mutableFruitList) // 輸出:[蘋果, 香蕉]

// 3. 清空集合
mutableFruitList.clear()
println(mutableFruitList) // 輸出:[]

(4)遍歷元素:三種常用方式

  • 普通 for 循環(huán):通過索引遍歷;
  • for-in 循環(huán):直接遍歷元素(推薦,簡潔);
  • forEach 高階函數(shù):函數(shù)式遍歷(更靈活,支持 lambda 邏輯)。
val fruitList = listOf("蘋果", "香蕉", "橙子")

// 1. 普通 for 循環(huán)(通過索引)
for (i in 0 until fruitList.size) {
    println("索引 $i:${fruitList[i]}")
}

// 2. for-in 循環(huán)(直接遍歷元素)
for (fruit in fruitList) {
    println("水果:$fruit")
}

// 3. forEach 高階函數(shù)(lambda 表達(dá)式)
fruitList.forEach { fruit ->
    println("forEach 遍歷:$fruit")
}
// 簡化:若 lambda 參數(shù)僅用一次,可用 it 代替
fruitList.forEach {
    println("簡化 forEach:$it")
}

(5)排序:sorted 系列方法

Kotlin 提供了豐富的排序 API,無需手動實(shí)現(xiàn)排序邏輯:

  • sorted():默認(rèn)升序排序(適用于數(shù)值、字符串等可比較類型);
  • sortedDescending():降序排序;
  • sortedBy(selector):按指定屬性排序(比如按對象的年齡、價格排序);
  • sortedByDescending(selector):按指定屬性降序排序。

示例(含普通數(shù)據(jù)和對象數(shù)據(jù)):

// 1. 數(shù)值 List 排序
val numList = listOf(3, 1, 4, 2)
val sortedAsc = numList.sorted() // 升序:[1, 2, 3, 4]
val sortedDesc = numList.sortedDescending() // 降序:[4, 3, 2, 1]
println("升序:$sortedAsc,降序:$sortedDesc")

// 2. 對象 List 排序(按屬性)
data class Student(val name: String, val score: Int)
val studentList = listOf(
    Student("張三", 85),
    Student("李四", 92),
    Student("王五", 78)
)
// 按分?jǐn)?shù)升序排序
val sortedByScoreAsc = studentList.sortedBy { it.score }
// 按分?jǐn)?shù)降序排序
val sortedByScoreDesc = studentList.sortedByDescending { it.score }
println("按分?jǐn)?shù)升序:$sortedByScoreAsc")
// 輸出:[Student(name=王五, score=78), Student(name=張三, score=85), Student(name=李四, score=92)]

(6)過濾:filter 方法

filter(predicate) 用于 “篩選符合條件的元素”,參數(shù)是一個 lambda 表達(dá)式(返回布爾值,true 保留元素,false 過濾掉)。

示例:

// 1. 篩選偶數(shù)
val numList = listOf(1, 2, 3, 4, 5, 6)
val evenList = numList.filter { it % 2 == 0 }
println("偶數(shù)列表:$evenList") // 輸出:[2, 4, 6]

// 2. 篩選長度大于 2 的字符串
val strList = listOf("a", "ab", "abc", "abcd")
val longStrList = strList.filter { it.length > 2 }
println("長度>2的字符串:$longStrList") // 輸出:[abc, abcd]

// 3. 篩選分?jǐn)?shù)>=80的學(xué)生
data class Student(val name: String, val score: Int)
val studentList = listOf(
    Student("張三", 85),
    Student("李四", 75),
    Student("王五", 90)
)
val goodStudents = studentList.filter { it.score >= 80 }
println("分?jǐn)?shù)>=80的學(xué)生:$goodStudents")
// 輸出:[Student(name=張三, score=85), Student(name=王五, score=90)]


三、Set 集合:無序、不可重復(fù)的 “數(shù)據(jù)集合”

Set 適合存儲 “需要去重” 的數(shù)據(jù)(比如用戶 ID、標(biāo)簽列表),核心特性是無序(無索引,不能通過索引訪問)、不可重復(fù)(添加重復(fù)元素會自動忽略) 。

1. Set 的核心特性回顧

  • 無序:元素沒有固定位置,遍歷順序可能與插入順序不同(普通 HashSet);
  • 不可重復(fù):基于 equals()hashCode() 判斷元素是否重復(fù)(若自定義對象,需重寫這兩個方法);
  • 不可變 Set(Set):僅支持查詢,無修改方法;
  • 可變 Set(MutableSet):支持添加、刪除元素。

2. Set 的常用操作(附代碼示例)

(1)添加元素:僅可變 Set 支持

add(element) 方法,重復(fù)元素會自動忽略(無報錯,返回 false 表示添加失?。?。

val mutableTagSet = mutableSetOf("Kotlin", "Android", "Java")
// 1. 添加新元素(成功,返回 true)
val addSuccess = mutableTagSet.add("Jetpack")
// 2. 添加重復(fù)元素(失敗,返回 false,集合無變化)
val addFail = mutableTagSet.add("Kotlin")

println(mutableTagSet) // 輸出:[Kotlin, Android, Java, Jetpack](無序)
println("添加新元素成功?$addSuccess,添加重復(fù)元素成功?$addFail") 
// 輸出:添加新元素成功?true,添加重復(fù)元素成功?false

(2)判斷元素是否存在:contains 方法

Set 的 contains(element) 方法效率極高(基于哈希表,時間復(fù)雜度 O (1)),適合頻繁判斷 “元素是否存在” 的場景。

val tagSet = setOf("Kotlin", "Android", "Java")
// 判斷是否包含 "Android"
val hasAndroid = tagSet.contains("Android")
// 判斷是否包含 "iOS"
val hasIos = tagSet.contains("iOS")

println("包含 Android?$hasAndroid,包含 iOS?$hasIos") 
// 輸出:包含 Android?true,包含 iOS?false

// 簡化寫法:用 in 關(guān)鍵字(等價于 contains)
val hasKotlin = "Kotlin" in tagSet
println("包含 Kotlin?$hasKotlin") // 輸出:true

(3)集合運(yùn)算:交集、并集、差集

Set 天然支持 “數(shù)學(xué)集合運(yùn)算”,Kotlin 直接提供了對應(yīng)的 API,無需手動實(shí)現(xiàn):

  • 交集(intersect):兩個集合的 “共有元素”;
  • 并集(union):兩個集合的 “所有元素(去重)”;
  • 差集(subtract):當(dāng)前集合 “減去另一個集合的元素后剩余的元素”。

示例:

val setA = setOf(1, 2, 3, 4)
val setB = setOf(3, 4, 5, 6)

// 1. 交集:共有的元素(3,4)
val intersection = setA.intersect(setB)
// 2. 并集:所有元素去重(1,2,3,4,5,6)
val union = setA.union(setB)
// 3. 差集:setA 減去 setB 的元素(1,2)
val subtract = setA.subtract(setB)

println("交集:$intersection,并集:$union,差集:$subtract")
// 輸出:交集:[3, 4],并集:[1, 2, 3, 4, 5, 6],差集:[1, 2]

(4)遍歷元素:僅支持 for-in 和 forEach

由于 Set 無序,沒有索引,不能用 “普通 for 循環(huán)(索引遍歷)”,只能直接遍歷元素:

val colorSet = setOf("紅色", "綠色", "藍(lán)色")

// 1. for-in 循環(huán)
for (color in colorSet) {
    println("for-in 遍歷:$color")
}

// 2. forEach 高階函數(shù)
colorSet.forEach {
    println("forEach 遍歷:$it")
}


四、Map 集合:鍵值對、鍵唯一的 “數(shù)據(jù)字典”

Map 適合存儲 “鍵值對應(yīng)” 的數(shù)據(jù)(比如用戶信息:id -> 用戶對象、配置項:key -> 配置值),核心特性是鍵值對存儲、鍵唯一(重復(fù)鍵會覆蓋舊值)、值可重復(fù)。

1. Map 的核心特性回顧

  • 鍵值對(key-value):每個元素由 “鍵” 和 “值” 組成,通過鍵獲取值;
  • 鍵唯一:同一 Map 中不能有重復(fù)鍵,重復(fù) put 會覆蓋舊值;
  • 值可重復(fù):不同鍵可以對應(yīng)相同的值;
  • 不可變 Map(Map):僅支持查詢,無修改方法;
  • 可變 Map(MutableMap):支持添加、修改、刪除鍵值對。

2. Map 的常用操作(附代碼示例)

(1)獲取值:get 方法與 [] 運(yùn)算符

  • get(key):根據(jù)鍵獲取值,若鍵不存在,返回 null
  • [key]:簡化寫法(等價于 get(key));
  • getOrDefault(key, defaultValue):鍵不存在時返回默認(rèn)值(避免 null)。

示例:

val userMap = mapOf(
    "name" to "張三",
    "age" to 20,
    "gender" to "男"
)

// 1. get(key) 方法
val name1 = userMap.get("name")
// 2. [] 簡化寫法(推薦)
val age1 = userMap["age"]
// 3. 鍵不存在,返回 null
val address1 = userMap["address"]
// 4. getOrDefault:鍵不存在時返回默認(rèn)值
val address2 = userMap.getOrDefault("address", "未知地址")

println("姓名:$name1,年齡:$age1,地址1:$address1,地址2:$address2")
// 輸出:姓名:張三,年齡:20,地址1:null,地址2:未知地址

(2)添加 / 修改鍵值對:僅可變 Map 支持

  • put(key, value):添加或修改鍵值對(鍵存在則修改,不存在則添加);
  • [key] = value:簡化寫法(等價于 put);
  • putAll(fromMap):批量添加另一個 Map 的鍵值對。

示例:

val mutableUserMap = mutableMapOf(
    "name" to "李四",
    "age" to 18
)

// 1. 添加新鍵值對(address 不存在,添加)
mutableUserMap.put("address", "北京市")
// 2. 修改已有鍵值對(age 存在,修改為 19)
mutableUserMap["age"] = 19
// 3. 批量添加
val extraMap = mapOf("phone" to "13800138000", "email" to "lisi@example.com")
mutableUserMap.putAll(extraMap)

println(mutableUserMap)
// 輸出:{name=李四, age=19, address=北京市, phone=13800138000, email=lisi@example.com}

(3)遍歷元素:三種常用方式

Map 的遍歷分為 “遍歷鍵”“遍歷值”“遍歷鍵值對”,按需選擇:

val userMap = mapOf(
    "name" to "張三",
    "age" to 20,
    "gender" to "男"
)

// 1. 遍歷鍵(通過 keys 屬性)
println("遍歷鍵:")
for (key in userMap.keys) {
    println("鍵:$key")
}

// 2. 遍歷值(通過 values 屬性)
println("遍歷值:")
for (value in userMap.values) {
    println("值:$value")
}

// 3. 遍歷鍵值對(最常用)
println("遍歷鍵值對:")
// 方式1:for-in 循環(huán)(解構(gòu)賦值:將 key-value 拆分為兩個變量)
for ((key, value) in userMap) {
    println("$key: $value")
}
// 方式2:forEach 高階函數(shù)(lambda 參數(shù)為 (key, value))
userMap.forEach { (key, value) ->
    println("$key -> $value")
}

(4)判斷鍵 / 值是否存在

  • containsKey(key):判斷鍵是否存在;
  • containsValue(value):判斷值是否存在(效率低于 containsKey,因為需要遍歷所有值)。

示例:

val userMap = mapOf(
    "name" to "張三",
    "age" to 20,
    "gender" to "男"
)

// 判斷鍵是否存在
val hasNameKey = userMap.containsKey("name")
val hasAddressKey = userMap.containsKey("address")

// 判斷值是否存在
val hasAge20 = userMap.containsValue(20)
val hasAge30 = userMap.containsValue(30)

println("有 name 鍵?$hasNameKey,有 address 鍵?$hasAddressKey")
// 輸出:有 name 鍵?true,有 address 鍵?false
println("有值 20?$hasAge20,有值 30?$hasAge30")
// 輸出:有值 20?true,有值 30?false


五、集合的高階函數(shù)操作:簡化代碼的 “神器”

Kotlin 集合框架的一大亮點(diǎn)是內(nèi)置了大量高階函數(shù),可以用 “函數(shù)式編程” 的方式處理集合,大幅減少模板代碼(比如無需手動寫循環(huán)、判斷)。本節(jié)課重點(diǎn)講解最常用的 6 類高階函數(shù):轉(zhuǎn)換、過濾、排序、聚合、分組、關(guān)聯(lián)。

1. 轉(zhuǎn)換:map 方法(將元素 “變形”)

map(transform) 用于 “將集合中的每個元素按規(guī)則轉(zhuǎn)換為新元素”,返回一個新集合(元素類型可與原集合不同)。

示例(多種轉(zhuǎn)換場景):

// 1. 數(shù)值轉(zhuǎn)換:每個元素乘 2
val numList = listOf(1, 2, 3, 4)
val doubledList = numList.map { it * 2 }
println("數(shù)值乘 2:$doubledList") // 輸出:[2, 4, 6, 8]

// 2. 字符串轉(zhuǎn)換:每個字符串添加前綴
val strList = listOf("蘋果", "香蕉", "橙子")
val prefixedList = strList.map { "水果:$it" }
println("添加前綴:$prefixedList") // 輸出:[水果:蘋果, 水果:香蕉, 水果:橙子]

// 3. 對象轉(zhuǎn)換:提取對象的某個屬性(常用?。?data class Student(val name: String, val score: Int)
val studentList = listOf(
    Student("張三", 85),
    Student("李四", 92),
    Student("王五", 78)
)
// 提取所有學(xué)生的姓名,生成姓名列表
val nameList = studentList.map { it.name }
// 提取所有學(xué)生的分?jǐn)?shù),生成分?jǐn)?shù)列表
val scoreList = studentList.map { it.score }
println("學(xué)生姓名列表:$nameList") // 輸出:[張三, 李四, 王五]
println("學(xué)生分?jǐn)?shù)列表:$scoreList") // 輸出:[85, 92, 78]

2. 過濾:filter 系列方法(篩選元素)

除了前面講過的 filter(基礎(chǔ)篩選),Kotlin 還提供了更細(xì)分的過濾方法,滿足不同場景:

  • filterNot(predicate):反向篩選(保留 false 的元素);
  • filterIsInstance<T>():按類型篩選(保留指定類型的元素);
  • filterNotNull():篩選非 null 元素(適合可空類型集合)。

示例:

// 1. filterNot:反向篩選(保留偶數(shù)以外的元素)
val numList = listOf(1, 2, 3, 4, 5)
val oddList = numList.filterNot { it % 2 == 0 }
println("非偶數(shù)列表:$oddList") // 輸出:[1, 3, 5]

// 2. filterIsInstance:按類型篩選(保留字符串元素)
val mixedList = listOf(1, "蘋果", 3.14, "香蕉", true)
val stringList = mixedList.filterIsInstance<String>()
println("字符串列表:$stringList") // 輸出:[蘋果, 香蕉]

// 3. filterNotNull:篩選非 null 元素
val nullableList = listOf("張三", null, "李四", null, "王五")
val nonNullList = nullableList.filterNotNull()
println("非 null 列表:$nonNullList") // 輸出:[張三, 李四, 王五]

3. 排序:sorted 系列方法(進(jìn)階)

除了前面講過的基礎(chǔ)排序,還有兩個常用進(jìn)階排序方法:

  • sortedWith(comparator):自定義比較器排序(適合復(fù)雜排序邏輯);
  • reversed():反轉(zhuǎn)集合順序(基于當(dāng)前順序反轉(zhuǎn))。

示例:

// 1. sortedWith:自定義比較器(按字符串長度排序)
val strList = listOf("apple", "banana", "cherry", "date")
// 按字符串長度升序排序(短的在前)
val sortedByLength = strList.sortedWith(compareBy { it.length })
println("按長度排序:$sortedByLength") // 輸出:[date, apple, banana, cherry]

// 2. reversed:反轉(zhuǎn)順序
val numList = listOf(1, 2, 3, 4)
val reversedList = numList.reversed()
println("反轉(zhuǎn)后:$reversedList") // 輸出:[4, 3, 2, 1]

4. 聚合:count、sum、max、min(統(tǒng)計數(shù)據(jù))

聚合函數(shù)用于 “對集合數(shù)據(jù)進(jìn)行統(tǒng)計計算”,返回單個結(jié)果值,常用的有:

  • count(predicate?):統(tǒng)計元素個數(shù)(可帶條件,無條件則統(tǒng)計總個數(shù));
  • sumOf(selector):計算數(shù)值總和(推薦,支持 Int、Long、Double 等);
  • maxOf(selector):獲取最大值(按指定屬性);
  • minOf(selector):獲取最小值(按指定屬性);
  • averageOf(selector):計算平均值(僅數(shù)值類型)。

示例:

data class Product(val name: String, val price: Double, val stock: Int)
val productList = listOf(
    Product("手機(jī)", 2999.0, 50),
    Product("平板", 1999.0, 30),
    Product("耳機(jī)", 499.0, 100),
    Product("手表", 1299.0, 20)
)

// 1. count:統(tǒng)計商品總數(shù),及價格>1000的商品數(shù)
val totalCount = productList.count() // 總個數(shù):4
val expensiveCount = productList.count { it.price > 1000 } // 價格>1000的個數(shù):3
println("商品總數(shù):$totalCount,高價商品數(shù):$expensiveCount")

// 2. sum:計算總庫存,及總金額(價格*庫存)
val totalStock = productList.sumOf { it.stock } // 總庫存:50+30+100+20=200
val totalAmount = productList.sumOf { it.price * it.stock } // 總金額
// 四舍五入(兼容寫法)
val roundedAmount = Math.round(totalAmount).toLong()
println("總庫存:$totalStock,總金額:$roundedAmount") 

// 3. max/min:獲取最高/最低價格(兼容舊版本)
val maxPrice = productList.maxOf { it.price } // 最高價格:2999.0
val minPrice = productList.minOf { it.price } // 最低價格:499.0
println("最高價格:$maxPrice,最低價格:$minPrice")

// 4. average:計算平均價格(兼容舊版本)
val avgPrice = productList.map { it.price }.average() // 先提取價格列表,再求平均
val roundedAvgPrice = avgPrice.toInt() // 簡化:直接轉(zhuǎn)為Int(自動截斷小數(shù))
println("平均價格:$roundedAvgPrice")

5. 分組:groupBy 方法(按條件分組)

groupBy(selector) 用于 “將集合按指定條件分組”,返回一個 Map

  • Map 的 key:分組條件(selector lambda 的返回值);
  • Map 的 value:該組的元素集合(與原集合元素類型相同)。

示例(常見分組場景):

// 1. 按性別分組(用戶列表)
data class User(val name: String, val gender: String, val age: Int)
val userList = listOf(
    User("張三", "男", 20),
    User("李四", "女", 18),
    User("王五", "男", 22),
    User("趙六", "女", 19)
)
val groupedByGender = userList.groupBy { it.gender }
println("按性別分組:$groupedByGender")
// 輸出:{男=[User(張三,男,20), User(王五,男,22)], 女=[User(李四,女,18), User(趙六,女,19)]}

// 2. 按分?jǐn)?shù)段分組(學(xué)生列表)
data class Student(val name: String, val score: Int)
val studentList = listOf(
    Student("張三", 85),
    Student("李四", 92),
    Student("王五", 78),
    Student("趙六", 65),
    Student("錢七", 59)
)
// 按分?jǐn)?shù)段分組:"優(yōu)秀"(>=90)、"良好"(80-89)、"及格"(60-79)、"不及格"(<60)
val groupedByScore = studentList.groupBy {
    when {
        it.score >= 90 -> "優(yōu)秀"
        it.score >= 80 -> "良好"
        it.score >= 60 -> "及格"
        else -> "不及格"
    }
}
println("按分?jǐn)?shù)段分組:$groupedByScore")
// 輸出:{良好=[Student(張三,85)], 優(yōu)秀=[Student(李四,92)], 及格=[Student(王五,78), Student(趙六,65)], 不及格=[Student(錢七,59)]}

6. 關(guān)聯(lián):associate 系列方法(生成 Map)

關(guān)聯(lián)函數(shù)用于 “將集合轉(zhuǎn)換為 Map”,常用的有三個:

  • associate(transform):自定義鍵值對(transform 返回 Pair<Key, Value>);
  • associateBy(selector):鍵為 selector 結(jié)果,值為原元素;
  • associateWith(selector):鍵為原元素,值為 selector 結(jié)果。

示例:

data class Student(val id: Int, val name: String, val score: Int)
val studentList = listOf(
    Student(1, "張三", 85),
    Student(2, "李四", 92),
    Student(3, "王五", 78)
)

// 1. associate:自定義鍵值對(id -> name)
val idToNameMap = studentList.associate { it.id to it.name }
println("id->name:$idToNameMap") // 輸出:{1=張三, 2=李四, 3=王五}

// 2. associateBy:鍵為 id,值為 Student 對象(常用!通過 id 快速查對象)
val idToStudentMap = studentList.associateBy { it.id }
// 通過 id 獲取 Student 對象
val student = idToStudentMap[2]
println("id=2 的學(xué)生:$student") // 輸出:Student(id=2, name=李四, score=92)

// 3. associateWith:鍵為 Student 對象,值為 score
val studentToScoreMap = studentList.associateWith { it.score }
println("student->score:$studentToScoreMap")
// 輸出:{Student(1,張三,85)=85, Student(2,李四,92)=92, Student(3,王五,78)=78}


六、集合的空安全與互操作性

1. 空安全:避免空指針

Kotlin 集合默認(rèn)支持空安全,需注意:

  • 不可變空集合:用 emptyList()/emptySet()/emptyMap()(返回非空集合,只是元素為空);
  • 可空元素集合:聲明時需指定類型為 List<T?>(比如 List<String?> 表示元素可空);
  • 過濾空元素:用 filterNotNull() 快速去除空元素(前面已講)。

示例:

// 可空元素集合
val nullableStrList: List<String?> = listOf("蘋果", null, "香蕉", null, "橙子")
// 過濾空元素,得到非空集合
val nonNullStrList: List<String> = nullableStrList.filterNotNull()
println(nonNullStrList) // 輸出:[蘋果, 香蕉, 橙子]

2. 與 Java 集合的互操作性

Kotlin 集合可以直接與 Java 集合互操作(無需手動轉(zhuǎn)換):

  • Kotlin 集合轉(zhuǎn) Java 集合:用 toJavaList()/toJavaSet()/toJavaMap()(需導(dǎo)入 kotlin.collections);
  • Java 集合轉(zhuǎn) Kotlin 集合:直接賦值(Kotlin 會自動識別為 Mutable 集合)。

示例:

// Java 代碼:返回一個 Java List
public class JavaCollectionUtils {
    public static List<String> getJavaList() {
        List<String> list = new ArrayList<>();
        list.add("Java-蘋果");
        list.add("Java-香蕉");
        return list;
    }
}
// Kotlin 代碼:使用 Java 集合
import com.example.JavaCollectionUtils

fun main() {
    // Java List 轉(zhuǎn) Kotlin 集合(自動轉(zhuǎn)為 MutableList)
    val kotlinList: MutableList<String> = JavaCollectionUtils.getJavaList()
    kotlinList.add("Kotlin-橙子")
    println(kotlinList) // 輸出:[Java-蘋果, Java-香蕉, Kotlin-橙子]

    // Kotlin 集合轉(zhuǎn) Java 集合
    val kotlinSet = setOf("Kotlin-1", "Kotlin-2")
    val javaSet: java.util.Set<String> = kotlinSet.toJavaSet()
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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