List 是一个有序集合,可通过索引(反映元素位置的整数)访问元素。元素可以在 list 中出现多次。列
Set 是唯一元素的集合。它反映了集合(set)的数学抽象:一组无重复的对象。一般来说 set 中元素的顺序并不重要。
Map(或者字典)是一组键值对。键是唯一的,每个键都刚好映射到一个值。值可以重复。map 对于存储对象之间的逻辑连接非常有用,
注意:
1.更改可变集合不需要必须用 var
定义的变量:写操作修改同一个可变集合对象,因此引用不会改变
[Collection
]是集合层次结构的根。此接口表示一个只读集合的共同行为:检索大小、检测是否为成员等等。 Collection
继承自 Iterable
接口,它定义了迭代元素的操作。
[MutableCollection
]是一个具有写操作的 Collection
接口,
在 Kotlin 中,List
的默认实现是 [ArrayList
],可以将其视为可调整大小的数组
Set
的默认实现 - [LinkedHashSet
] – 保留元素插入的顺序。 因此,依赖于顺序的函数,例如 first()
或 last()
,会在这些 set
上返回可预测的结果。
另一种实现方式 – HashSet
– 不声明元素的顺序,所以在它上面调用这些函数会返回不可预测的结果。但是,HashSet
只需要较少的内存来存储相同数量的元素
Map
的默认实现 – [LinkedHashMap
] 迭代 Map 时保留元素插入的顺序。 反之,另一种实现 – HashMap
– 不声明元素的顺序
创建集合的最常用方法是使用标准库函数 listOf()、setOf()、mutableListOf()、mutableSetOf()。
Map 也有这样的函数 mapOf() 与 mutableMapOf()
//空集合list
val list1 = listOf<String>()
//固定大小集合list
val list2 = listOf<String>("1","2")
//可变大小集合list
val list3 = mutableListOf<String>("1","2")
//空set
val set1 = setOf<String>()
//固定set
val set2 = setOf<String>("1","2")
//可变大小set
val set3 = mutableSetOf<String>("1","2")
//空set
val map1 = mapOf<String,String>()
val map2 = mapOf<String,String>("1" to "A")
//可变map
val map3 = mutableMapOf<String,String>()
注意,to
符号创建了一个短时存活的 Pair
对象,因此建议仅在性能不重要
时才使用它。 为避免过多的内存使用,请使用其他方法。例如,可以创建可写 Map 并使用写入操作填充它。 apply()
函数可以帮助保持初始化流畅。 apply()
函数可以帮助保持初始化流畅。
val numbersMap = mutableMapOf<String, String>().apply { this["one"] = "1"; this["two"] = "2" }
emptyList()、emptySet() 与 emptyMap()。
list初始化
val doubled = List(3, { it * 2 }) // 如果你想操作这个集合,应使用 MutableList
println(doubled)
//具体类型的构造函数
val linkedList = LinkedList<String>(listOf("one", "two", "three"))
val presizedSet = HashSet<Int>(32)
复制
创建与现有集合具有相同元素的集合,可以使用复制操作
在特定时刻通过集合复制函数,例如toList()
、toMutableList()
、toSet()
等等。这些方法可以创建新的集合对象。
val sourceList = mutableListOf(1, 2, 3)
val copyList = sourceList.toMutableList()
val readOnlyCopyList = sourceList.toList()
sourceList.add(4)
转换为其他类型
val sourceList = mutableListOf(1, 2, 3)
val copySet = sourceList.toMutableSet()
copySet.add(3)
copySet.add(4)
println(copySet)
更多:filter map mapIndexed
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter { it.length > 3 }
println(longerThan3)
//映射map
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
println(numbers.mapIndexed { idx, value -> value * idx })
[3, 6, 9]
[0, 2, 6]
//associateWith 关联生成map
val numbers = listOf("one", "two", "three", "four")
println(numbers.associateWith { it.length })
{one=3, two=3, three=5, four=4}
对于遍历集合元素, Kotlin 标准库支持 迭代器 的常用机制——对象可按顺序提供对元素的访问权限,而不会暴露集合的底层结构
Iterable
接口的继承者(包括 Set
与 List
)可以通过调用 iterator()
函数获得迭代器
val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
println(numbersIterator.next())
}
**List 迭代器**
val numbers = listOf("one", "two", "three", "four")
val listIterator = numbers.listIterator()
while (listIterator.hasNext()) listIterator.next()
//为了迭代可变集合,于是有了 MutableIterator 来扩展 Iterator 使其具有元素删除函数 remove() 。因此,可以在迭代时从集合中删除元素。插入和替换元素。
val numbers = mutableListOf("one", "two", "three", "four")
val mutableIterator = numbers.iterator()
mutableIterator.next()
mutableIterator.remove()
mutableListIterator.add("two")
mutableListIterator.next()
mutableListIterator.set("three")
可变迭代器 MutableIterator
MutableIterator
来扩展 Iterator
使其具有元素删除函数 remove()
、add() set()
val numbers = mutableListOf("one", "two", "three", "four")
val mutableIterator = numbers.iterator()
mutableIterator.next()
mutableIterator.remove()
mutableListIterator.set("three")
mutableListIterator.add("two")
println("After removal: $numbers")
Kotlin 可通过调用 kotlin.ranges
包中的 [rangeTo()
]函数及其操作符形式的 ..
轻松地创建两个值的区间。 通常,rangeTo()
会辅以 in
或 !in
函数。
//包含头尾值
if (i in 1..4) { // 等同于 1 <= i && i <= 4
print(i)
}
整数类型区间(IntRange
、LongRange
、CharRange
)还有一个拓展特性:可以对其进行迭代。 这些区间也是相应整数类型的等差数列。
//downTo 反向迭代
for (i in 4 downTo 1) print(i)
// step 函数
for (i in 1..8 step 2) print(i)
//until 函数 算头不算尾
for (i in 1 until 10) { // i in [1, 10), 10被排除
print(i)
}
要为类创建一个区间,请在区间起始值上调用 rangeTo()
函数,并提供结束值作为参数。 rangeTo()
通常以操作符 ..
形式调用。
class Version(val major: Int, val minor: Int): Comparable<Version> {
override fun compareTo(other: Version): Int {
if (this.major != other.major) {
return this.major - other.major
}
return this.minor - other.minor
}
}
fun main() {
val versionRange = Version(1, 11)..Version(1, 30)
println(Version(0, 9) in versionRange)
println(Version(1, 20) in versionRange)
}
如上个示例所示,整数类型的区间(例如 Int
、Long
与 Char
)可视为等差数列。 在 Kotlin 中,这些数列由特殊类型定义:IntProgression
、LongProgression
与 CharProgression
。
数列具有三个基本属性:first
元素、last
元素和一个非零的 step
for (int i = first; i <= last; i += step) {
// ……
}
for (i in 1..10) print(i)
数列的 last
元素是这样计算的:
(last - first) % step == 0
的最大值。(last - first) % step == 0
的最小值。除集合外 还有一种容器 Sequenec, 序列提供与 Iterable
相同的函数,但实现另一种方法来进行多步骤集合处理。当 Iterable
的处理包含多个步骤时,它们会优先执行:每个处理步骤完成并返回其结果——中间集合。 在此集合上执行以下步骤。反过来,序列的多步处理在可能的情况下会延迟执行:仅当请求整个处理链的结果时才进行实际计算。
val n = sequenecof("one","two")
如果已经有一个iterable对象,可以调用asSequence()
val num = listof("one","two")
val numsequ = num.asSequnce();
通过使用计算其元素的函数来构建序列。要基于函数构建序列,请以该函数作为参数调用 generateSequence()
。 (可选)可以将第一个元素指定为显式值或函数调用的结果。 当提供的函数返回 null
时,序列生成停止。,以下示例中的序列是无限的
//首次1执行,返回的结果+2再次执行
val oddNumbers = generateSequence(1) { it + 2 } // `it` 是上⼀个元素
println(oddNumbers.take(5).toList())//执行5次
//要使用 generateSequence() 创建有限序列,请提供一个函数,该函数在需要的最后一个元素之后返回 null
val oddNumbersLessThan10 = generateSequence(1) { if (it + 2 < 10) it + 2 else null }
println(oddNumbersLessThan10.count())
有一个函数可以逐个或按任意大小的组块生成序列元素——sequence()
函数。
此函数采用一个 lambda 表达式,其中包含 yield()
与 yieldAll()
函数的调用。 它们将一个元素返回给序列使用者,并暂停 sequence()
的执行,直到使用者请求下一个元素。
yield()
使用单个元素作为参数;
yieldAll()
中可以采用 Iterable
对象、Iterable
或其他 Sequence
。
yieldAll()
的 Sequence
参数可以是无限的。
当然,这样的调用必须是最后一个:之后的所有调用都永远不会执行。
val oddNumbers = sequence {
yield(1)
yieldAll(listOf(3, 5))
yieldAll(generateSequence(7) { it + 2 })
}
println(oddNumbers.take(5).toList())
分为以下几类:
map()
或 filter()
。 无状态操作还可能需要少量常数个状态来处理元素,例如 take()
与 drop()
。如果序列操作返回延迟生成的另一个序列,则称为 中间序列。 否则,该操作为 末端 操作。 末端操作的示例为 toList()
或 sum()
。只能通过末端操作才能检索序列元素。
序列可以多次迭代;但是,某些序列实现可能会约束自己仅迭代一次。其文档中特别提到了这一点
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(" ")
// 将列表转换为序列
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")
// 末端操作:以列表形式获取结果。
println(lengthsSequence.toList())
结果:
Lengths of first 4 words longer than 3 chars
filter: The
filter: quick
length: 5
filter: brown
length: 5
filter: fox
filter: jumps
length: 5
filter: over
length: 4
[5, 5, 5, 4]
集合操作在标准库中以两种方式声明:集合接口的成员函数和扩展函数
创建自己的集合接口实现时,必须实现其成员函数。 为了使新实现的创建更加容易,请使用标准库中集合接口的框架实现:AbstractCollection
、AbstractList
、AbstractSet
、AbstractMap
及其相应可变抽象类。
其他集合操作被声明为扩展函数。这些是过滤、转换、排序和其他集合处理功能。
转换从另⼀个集合的元素上的函数结果创建⼀个集合
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
转换是根据两个集合中具有相同位置的元素构建配对,不是map形式
//zip() 返回 Pair 对象的列表( List )
val colors = listOf("red", "brown", "grey")
val animals = listOf("fox", "bear", "wolf")
println(colors zip animals)
关联 转换允许从集合元素和与其关联的某些值构建 Map
val numbers = listOf("one", "two", "three", "four")
println(numbers.associateWith { it.length })
结果:
{one=3, two=3, three=5, four=4}
去除多层集合内部的层级
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
println(numberSets.flatten())
val numbers = listOf("one", "two", "three", "four")
println(numbers)
println(numbers.joinToString())
在Kotlin中,过滤条件由 谓词 定义——接受一个集合元素并且返回布尔值的 lambda 表达式:true
说明给定元素与谓词匹配,false
则表示不匹配
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter { it.length > 3 }
println(longerThan3)
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap)
filterIndexed():使用元素在集合中的位置过滤
filterNot() 反向过滤
filterIsInstance() 返回给定类型的集合元素
val numbers = listOf(null, 1, "two", 3.0, "four")
println("All String elements in upper case:")
numbers.filterIsInstance().forEach {
println(it.toUpperCase())
}
filterNotNull()返回所有的非空元素
partition() 通过一个谓词过滤集合并且将不匹配的元素存放在一个单独的列表中
val numbers = listOf("one", "two", "three", "four")
//匹配的和不匹配的存入集合
val (match, rest) = numbers.partition { it.length > 3 }
println(match)
println(rest)
result:
[three, four]
[one, two]
any()
返回 true
。none()
返回 true
。all()
返回 true
all()
都会返回 true
。这种行为在逻辑上被称为 vacuous truth。val numbers = listOf("one", "two", "three", "four")
println(numbers.any { it.endsWith("e") })
println(numbers.none { it.endsWith("a") })
println(numbers.all { it.endsWith("e") })
println(emptyList().all { it > 5 }) // vacuous truth
与
minus` 操作符val numbers = listOf("one", "two", "three", "four")
//Plus 相当于累加
val plusList = numbers + "five"
//minus 去除
val minusList = numbers - listOf("three", "four")
println(plusList)
println(minusList)
[one, two, three, four, five]
[one, two]
基本函数 groupBy()
使用一个 lambda 函数并返回一个 Map
。 在此 Map 中,每个键都是 lambda 结果,而对应的值是返回此结果的元素 List
。 例如,可以使用此函数将 String
列表按首字母分组。
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.groupBy { it.first().toUpperCase() })
println(numbers.groupBy(keySelector = { it.first() }, valueTransform = { it.toUpperCase() }))
{O=[one], T=[two, three], F=[four, five]}
{o=[ONE], t=[TWO, THREE], f=[FOUR, FIVE]}
slice()
返回具有给定索引的集合元素列表
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3))
println(numbers.slice(0..4 step 2))
println(numbers.slice(setOf(3, 5, 0)))
从头开始获取指定数量的元素,请使用 take()
函数。 从尾开始获取指定数量的元素,请使用 takeLast()
。
从头或从尾去除给定数量的元素,请调用 drop()
或 dropLast()
函数。
val numbers = listOf("one", "two", "three", "four", "five", "six")
//从头获取三个
println(numbers.take(3))
println(numbers.takeLast(3))
//从头去除一个
println(numbers.drop(1))
println(numbers.dropLast(5))
[one, two, three]
[four, five, six]
[two, three, four, five, six]
[one]
要将集合分解为给定大小的“块”
fun main() {
val numbers = (0..10).toList()
//每3个元素一块数据
println(numbers.chunked(3))
}
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
可以检索给定大小的集合元素中所有可能区间。windowed()
返回从每个集合元素开始的元素区间(窗口)
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.windowed(2))
step
定义两个相邻窗口的第一个元素之间的距离
partialWindows
包含从集合末尾的元素开始的较小的窗口
val numbers = (1..10).toList()
println(numbers.windowed(3, step = 2, partialWindows = true))
println(numbers.windowed(3) { it.sum() })
result:
[[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]
[6, 9, 12, 15, 18, 21, 24, 27]
// elementAt(index) 按下标取
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.elementAt(3))
//函数 first() 和 last() 按照条件获取
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.first { it.length > 3 })
println(numbers.last { it.startsWith("f") })
random() //函数 随机取
contains() //函数 是否存在
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.elementAtOrNull(5))
println(numbers.elementAtOrElse(5) { index -> "The value for index $index is undefined"})
类似Java里对象之间可以比较,比较就可以排序。可以继承compareable,重写方法compareTo
class Version(val major: Int, val minor: Int): Comparable<Version> {
override fun compareTo(other: Version): Int {
if (this.major != other.major) {
return this.major - other.major
} else if (this.minor != other.minor) {
return this.minor - other.minor
} else return 0
}
}
fun main() {
println(Version(1, 2) > Version(1, 3))
println(Version(2, 0) > Version(1, 5))
}
//如需为类型定义自定义顺序,可以为其创建一个 Comparator。 Comparator 包含 compare() 函数:它接受一个类的两个实例并返回它们之间比较的整数结果。
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
Comparator
的一种比较简短的方式是标准库中的 compareBy()
函数
println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
基本的函数
sorted()
升序
sortedDescending()
降序
reversed()
函数以相反的顺序检索集合。
asReversed()
反向函数
shuffled()
函数 随机产生一个新的list
min()
与 max()
分别返回最小和最大的元素;average()
返回数字集合中元素的平均值;sum()
返回数字集合中元素的总和;count()
返回集合中元素的数量;getOrElse()
提供用于计算默认值的函数,如果集合中不存在索引,则返回默认值。
getOrNull()
返回 null
作为默认值。
这两个方法能避免找不到元素异常
subList 取一部分
indexOf()
获取下标
lastIndexOf()
binarySearch()
函数 二分查找
查找交集、并集或差集。
要将两个集合合并为一个(并集),可使用 union()
函数。
要查找两个集合中都存在的元素(交集),请使用 intersect()
。
要查找另一个集合中不存在的集合元素(差集),请使用 subtract()
val numbers = setOf("one", "two", "three")
println(numbers union setOf("four", "five"))
println(setOf("four", "five") union numbers)
println(numbers intersect setOf("two", "one"))
println(numbers subtract setOf("three", "four"))
println(numbers subtract setOf("four", "three")) // 相同的输出
[one, two, three, four, five]
[four, five, one, two, three]
[one, two]
[one, two]
[one, two]
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
//根据key 去value
println(numbersMap.get("one"))
//另一种方式
println(numbersMap["one"])
println(numbersMap.getOrDefault("four", 10))
println(numbersMap["five"]) // null
//numbersMap.getValue("six")
getOrElse()
与 list 的工作方式相同:对于不存在的键,其值由给定的 lambda 表达式返回。getOrDefault()
如果找不到键,则返回指定的默认值。keys
是 Map 中所有键的集合, values
是 Map 中所有值的集合。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.keys)
println(numbersMap.values)
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
//根据filter过滤符合条件的数据
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap)
// filterKeys() 和 filterValues() 也可以通过两种形式过滤
plus
与 minus
操作val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
//累加map 集合数据,以pair形式添加
println(numbersMap + Pair("four", 4))
//如果存在key,会进行value的覆盖
println(numbersMap + Pair("one", 10))
//可以接收map形式的数据
println(numbersMap + mapOf("five" to 5, "one" to 11))
//minus 将根据左侧 Map 条目创建一个新 Map ,右侧操作数带有键的条目将被剔除。 因此,右侧操作数可以是单个键或键的集合: list 、 set 等。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap - "one")
println(numbersMap - listOf("two", "four"))
关于在可变 Map 中使用 plusAssign
(+=
)与 minusAssign
(-=
)运算符的详细信息
put
putall() 它的参数可以是 Map
或一组 Pair
: Iterable
、 Sequence
或 Array
。
+= 追加map数据
-= 移除map 数据
[] 设置新的数据
val numbersMap = mutableMapOf("one" to 1, "two" to 2)
numbersMap["three"] = 3 // 调用 numbersMap.set("three", 3)
numbersMap += mapOf("four" to 4, "five" to 5)
numbersMap -= "four" //根据key移除数据
println(numbersMap)
Remove()
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3, "threeAgain" to 3)
numbersMap.keys.remove("one")//根据key 移除
println(numbersMap)
numbersMap.values.remove(3) //根据value 移除
println(numbersMap)