【Kotlin精简】第2章 集合

1 简介

在 Kotlin 中集合主要分为可变集合只读集合,其中可变集合使用 "Mutable" 前缀 + 集合类名表示,比如 MutableListMutableSetMutableMap 等。而对于只读集合就是和 Java 中集合类名是一致。 Java 中的 List 非 Kotlin 中的 List , 因为 Kotlin 中的 List 是只读的而非可变,却有点类似于 Kotlin 中的 MutableList

  1. 只读集合:
    内部只具有访问元素的方法,不具有类似 add、remove、clear 之类修改集合的方法。比如 Collection 只读集合内部就没有 add、remove、clear 之类方法,只有 get 访问元素的方法.
  2. 可变集合
    在集合内部既具有访问元素的方法,也具有类似 add、remove、clear 之类修改集合的方法。比如 MutableCollection 可变集合内部就有 addremoveclear 之类方法。

集合是可变数量的一组条目。
List : 是有序集合,可以通过下标访问元素,元素可以重复。
Set : 是无序集合,有别于List集合的地方在于,1.没有下标,2.元素不允许重复。只能遍历获取参数,遍历参数的顺序与添加顺序相同。元素如果已经存在不进行添加。可以存储Null, 而且Null也是唯一的。
Map:是无序集合,通过键值对存储数据。每个键唯一。值可以重复。

集合主要就是ListSetMap,它们在Java中都有接口可以实现,
List --> ArrayList、LinkedList
Set --> HashSet
Map--> HashMap

1.1 List集合

kotlin 复制代码
	val list = ArrayList<String>()
	list.add("1")
	list.add("2")
	
	// 创建的是一个不可变的集合,该集合创建成功只能用于读取数据,不能增删改集合数据。
	val list1 = listOf("aa", "bb")
	// 创建的是一个可变的集合,可以进行增删改查操作。
	val list2 = mutableListOf("cc", "dd")
	
	// 遍历List集合需要使用for-in循环进行遍历
	for (content in list1){
		// 把遍历内容大写
		content.toUpperCase()
		print(content)	// 输出:aa bb
	}
	
	list2.add("ee")
	list2.addAll(list1)
	// 移除指定的元素对象。如果指定元素不存在,移除null。不会报错
	list2.remove("ee")
	// 移除参数集合中存在的所有元素。 
   	// 或者,你可以关键字作为参数来调用它;在这种情况下,函数移除关键字匹配true 的所有元素。
	list2.removeAll(list1)
	// retainAll() 与 removeAll() 相反,
   	// 它移除除参数集合中的元素之外的所有元素。
   	// 当与关键字一起使用时,它只留下与关键字匹配的元素。
	list2.retainAll(list)

1.2 Set集合

Set和List的用法其实一样,在初始化时会用到这几个方法:setof()mutableSetOf()

kotlin 复制代码
	// 不可变的集合
	val set1 = setOf("aa", "bb") 
	// 可变的集合
	val set2 = mutableSetOf("cc", "dd") 

	// 新增元素
   	set2.add("ee")
   	set2.addAll(set1)
   	
	// 移除指定的元素对象。如果指定元素不存在,移除null。不会报错
   	set2.remove("ee")
   	// 移除参数集合中存在的所有元素。 
   	// 或者,你可以关键字作为参数来调用它;在这种情况下,函数移除关键字匹配true 的所有元素。
   	set2.removeAll(set1)
   	// retainAll() 与 removeAll() 相反,
   	// 它移除除参数集合中的元素之外的所有元素。
   	// 当与关键字一起使用时,它只留下与关键字匹配的元素。
   	set2.retainAll(set1)

setof():创建的是一个不可变的集合,该集合创建成功只能用于读取数据,不能增删改集合数据。
mutableSetOf():创建的是一个可变的集合,可以进行增删改查操作。

在这里,Set集合List集合的区别需要注意的是,Set底层是使用Hash映射机制来存储数据的,因此集合中的元素无法保证有序。

----遍历和List一样,就不做解释了

1.3 Map集合

Map集合这里重点介绍,Map和前两者不同,Map是一种键值对形式的数据结构,因此在用法上和List、Set存在很大不同。

一般初始化Map时都需要创建一个HashMap

kotlin 复制代码
val map = HashMap<String, String>()
map.put("aa", "1")
map.put("bb", "2")

// 因为在Kotlin中,并不建议使用put()、get()方法对Map进行添加和读取数据,
// 而是使用这种类似下标的方式添加数据:
val map1 = HashMap<String, Int>()
map1["aa"] = 1
map1["bb"] = 2

// 当读取数据时
val text = map1["aa"]

// 移除对应的值,参数为key
map1.remove("aa")

然而,上面这种添加数据方式依然很繁琐,和List、Set一样,Map也有自己的方法mapof()、mutableMapOf()

kotlin 复制代码
// 不可变
val map1 = mapOf("aa" to 1, "bb" to 2)  
// 可变
val map2 = mutableMapOf("aa" to 1, "bb" to 2)  

mapof():创建的是一个不可变的集合,该集合创建成功只能用于读取数据,不能增删改集合数据。
mutableMapOf():创建的是一个可变的集合,可以进行增删改查操作。

遍历Map集合,也是使用的for-in循环,唯一区别在于,for-in循环中,map键值对变量一起申明到了一对括号中

kotlin 复制代码
fun main(){
    val map1 = mapOf("aa" to 1, "bb" to 2) 
    for ((content1, content2) in map1){
        print(content1 + "--" + content2)
    }
}

1.4 集合迭代器 Iterator

提供一种遍历集合元素的方法,而不暴露集合内部的实现。

1.4.1 迭代器的方式

只要实现了Iterable接口的类型,都提供迭代器。

下面是使用迭代器的3种方式:

  1. 使用next()
kotlin 复制代码
val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
    println(numbersIterator.next())
}
  1. 使用for...in
kotlin 复制代码
val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
    println(item)
}
  1. 使用forEach()
kotlin 复制代码
val numbers = listOf("one", "two", "three", "four")
numbers.forEach {
    println(it)
}

1.4.2 List 的迭代器

List 的迭代器是ListIterator类型,可以反向迭代:

kotlin 复制代码
val numbers = listOf("one", "two", "three", "four")
val listIterator = numbers.listIterator()
while (listIterator.hasNext()) listIterator.next()
println("Iterating backwards:")
while (listIterator.hasPrevious()) {
    print("Index: ${listIterator.previousIndex()}")
    println(", value: ${listIterator.previous()}")
}

// Iterating backwards:
// Index: 3, value: four
// Index: 2, value: three
// Index: 1, value: two
// Index: 0, value: one

1.4.3 可变迭代器

可变集合(MutableList, MutableSet, MutableMap)的迭代器都是MutableIterator类型,可以在迭代的过程中调用remove()方法删除元素。

kotlin 复制代码
val numbers = mutableListOf("one", "two", "three", "four") 
val mutableIterator = numbers.iterator()

mutableIterator.next()
mutableIterator.remove()

println("After removal: $numbers")
// After removal: [two, three, four]

另外,MutableList的迭代器是MutableListIterator类型,可以在迭代过程中插入替换元素。

kotlin 复制代码
val numbers = mutableListOf("one", "four", "four") 
val mutableListIterator = numbers.listIterator()

mutableListIterator.next()
mutableListIterator.add("two")
mutableListIterator.next()
mutableListIterator.set("three")

println(numbers)
// [one, two, three, four]

1.5 集合Range

使用rangeTo()可以创建范围,rangeTo()对应的操作符:...。

kotlin 复制代码
// 遍历范围
for (i in 1..4) print(i)

// 反序遍历:
for (i in 4 downTo 1) print(i)

// 反序遍历2:
for (i in (1..4).reversed()) print(i)

// 定义步长:
for (i in 1..8 step 2) print(i)

// 不包含末尾元素:
for (i in 1 until 10) print(i)

1.6 集合序列 Sequence

序列和迭代器的差别

Iterable遍历执行多步操作时,会先对所有元素执行一个步骤,将结果保存到中间集合中,然后再对中间集合中所有元素执行下一个步骤,以此类推。相当于,所有元素被并行处理。

Sequence遍历执行多步操作时,会对一个元素执行所有步骤,然后再对下一个元素执行所有步骤,以此类推。相当于,所有元素被串行处理。

kotlin 复制代码
// 1.通过元素创建
val s1 = sequenceOf(1, 2, 3)

// 2.通过Iterable创建
val list = listOf(1,2,3)
val s2 = list.asSequence()

// 3.通过generateSequence()函数创建

// 4.通过sequence()创建


// 例子:假设有很多单词,我们要过滤长度超过3个字母的单词,然后打印前4个这种单词的长度。
// Iterable的方式
val words = "The quick brown fox jumps over the lazy dog".split(" ")
val lengthsList = words.filter { println("filter: $it"); it.length > 3 }
    .map { println("length: ${it.length}"); it.length }
    .take(4)
println("Lengths of first 4 words longer than 3 chars:")
println(lengthsList)

// Sequence的方式
val words = "The quick brown fox jumps over the lazy dog".split(" ")
// 将 List 转换为序列
val wordsSequence = words.asSequence()
val lengthsSequence = wordsSequence.filter { println("filter: $it"); it.length > 3 }
    .map { println("length: ${it.length}"); it.length }
    .take(4)
println("Lengths of first 4 words longer than 3 chars")
// 终止操作: 以 List 形式获取结果
println(lengthsSequence.toList())
  1. filter()map()take()这些操作,在调用toList()后才开始执行。与上面Iterable相比,是"lazy"的。
  2. 当结果元素数量到达4个时,会停止处理,因为take(4)指定了最大元素数量。与上面Iterable相比,节省了操作步骤。
  3. Sequence处理执行了 18 步,而使用Iterable时则需要 23 步。

1.7 常用的集合函数式API

1.7.1 map()函数

它用于将每个元素都映射成一个另外的值,映射规则在Lambda表达式中指定,最终生成一个新的集合,

kotlin 复制代码
val list1 = listOf("aa", "bb") 
var newList = list1.map{ it.toUpperCase()}
for (content in list1){
    content.toUpperCase() //转换成大写模式
}

1.7.2 filter()函数

用于过滤集合中的数据,可以单独使用,也可以和map()一起使用

kotlin 复制代码
val list1 = listOf("aa", "bbbb", "cc") 
var list2 = list1.filter { it.length <= 2 }
                         .map { it.toUpperCase() }

1.7.3 any()函数

判断集合中是否至少存在一个元素满足指定条件

kotlin 复制代码
val list1 = listOf("aa", "bbbb", "cc") 
var anyResult = list1.any { it.length <= 2 }

1.7.4 all()函数

判断集合中是否所有元素都满足指定条件

kotlin 复制代码
val list1 = listOf("aa", "bbbb", "cc") 
var allResult = list1.all { it.length <= 2 }

1.7.5 maxBy()函数

定义一个集合,然后找出里面长度最长的元素,maxBy的工作原理是根据传入的条件来进行遍历,从而找打最大值

kotlin 复制代码
val list1 = listOf("aa", "bbbb", "cc") 
var maxLength = list1.maxBy { it.length }
print(maxLength)
相关推荐
潘潘潘22 分钟前
Android多线程机制简介
android
CYRUS_STUDIO2 小时前
利用 Linux 信号机制(SIGTRAP)实现 Android 下的反调试
android·安全·逆向
CYRUS_STUDIO2 小时前
Android 反调试攻防实战:多重检测手段解析与内核级绕过方案
android·操作系统·逆向
黄林晴6 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我6 小时前
flutter 之真手势冲突处理
android·flutter
法的空间7 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止7 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭7 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech7 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户2018792831677 小时前
为何Handler的postDelayed不适合精准定时任务?
android