Kotlin 语言基础语法及标准库
基础
Kotlin 变量和数据类型
不可变变量 val
关键字
类似java中final关键字,必须有初始值,且不更改变量的值
Error:(13, 5) Kotlin: Val cannot be reassigned
可变变量var
关键字
var myName = "china"
类型推断
// 没有指定变量类型,编译器自动判断类型为String
var website = "hello world"
// 指定变量类型
var website: String = "hello world"
// 先声明,后初始化值
var website: String
website = "hello world"
基础数据类型
- 数字:
Byte
、Short
、Long
、Int
、Float
、Double
Boolean
: true/falseChar
Array
String
Byte
fun main(args : Array) {
val num: Byte = 99
println("$num")
// 127
var bigByte: Byte = Byte.MAX_VALUE
// -128
var smallByte: Byte = Byte.MIN_VALUE
}
Short
fun main(args : Array) {
val num: Short = 29999
println("$num")
}
Int
fun main(args : Array) {
val num: Int = 123456
println("$num")
}
Long
fun main(args : Array) {
val num: Long = 12345678
println("$num")
}
Double
fun main(args : Array) {
val num = 101.99
println("$num")
}
Float
fun main(args : Array) {
val num = 101.99F
println("$num")
}
Boolean
fun main(args : Array) {
val boolValue = false
println("$boolValue")
}
Char
fun main(args : Array) {
val ch = 'A'
println("ch")
val ch2: Char
ch2 = 'Z'
println("ch2")
}
类型转换函数
toChar()
toInt()
toLong()
toFloat()
toDouble()
toByte()
toShort()
fun main(args : Array<String>){
println("4.554 to int: " + (4.554.toInt()))
println("66 to Char: " + (65.toChar()))
println("B to int: " + ('B'.toInt()))
}
String 字符串
// 常量字符串
val website = "BeginnersBook"
// """ """ 模版字符串
val longString = """Welcome to
Beginnersbook.com"""
// $变量
var name = "hello"
var name2 = "world"
name = name + " "+ name2
println("name is : $name")
获取字符串长度
.length
var name = "hello"
println("name length is : ${name.length}")
println("name length is :" + name.length)
字符串比较
equals()
compareTo()
fun main(args : Array<String>){
var str1 = "BeginnersBook"
var str2 = "beginnersbook"
// true 相同
println("String Equals? : "+ str1.equals(str2))
// == 0 相同
println("String Equals? :"+ str1.compareTo(str2) == 0 )
}
获取指定下标字符
.get(index)
截取子串
.subSequence(fromIndex,toIndex)
fromIndex
包含toIndex
排它
字符串是否包含
.contains()
数组
声明
arrayOf
- 包含多种类型
var arr = arrayOf(10,"hello",'h')
- 单个类型
var arr = arrayOf<Int>(1,2,3,4)
var arr = arrayOf<String>("A","B","C")
获取下标元素值
arr[index]
设置下标元素值
array[index] = 3
数组大小
.size
元素包含
.contains
范围 Range
for(num in 1..4){
println(num)
}
for(ch in 'A'..'E'){
println(ch)
}
判断元素值是否在范围内
in
fun main(args: Array<String>) {
val oneToTen = 1..10
print(3 in oneToTen)
}
顺序递增/递减
.rangeTo()
递增
.downTo()
递减
val oneToFive = 1.rangeTo(5) // 1,2,3,4,5
val sixToThree = 6.downTo(3) // 6,5,4,3
指定步长
.step()
val oneToTen = 1..10
// 1,3,5,7,9
val odd = oneToTen.step(2) // 1-10的数 自增2
条件 表达式
if
if ... else
if ... else if .. else
when 表达式
类似Java中的switch
case
语法
fun main(){
var ch = 'A'
when(ch){
'A' -> println("A is a Vowel")
'E' -> println("E is a Vowel")
'I' -> println("I is a Vowel")
'O' -> println("O is a Vowel")
'U','Z' -> println("U Z Hello")
else -> println("$ch is a Consonant")
}
}
也可以结合范围来判断
var num = 78
when(num) {
in 1..9 -> println("num is a single digit number")
in 10..99 -> println("num is a two digit number")
in 100..999 -> println("num is a three digit number")
else -> println("num has more than three digits")
}
For 循环
fun main(){
// 正常循环
val myArray = arrayOf("ab", "bc", "cd", "da")
for (str in myArray){
println(str)
}
// 带索引下标的循环
val myArray = arrayOf("Steve", "Robin", "Kate", "Lucy")
for((index, value) in myArray.withIndex()){
println("Value at ${index} index is: ${value}")
}
}
While 循环
while()
fun main(){
var num = 10
while(num>=5){
println("Loop: $num")
num--
}
}
do while 循环
do{} while()
至少循环一次。
fun main(){
var num = 100
do {
println("Loop: $num")
num++
}
while (num<=105)
}
break 终止外循环
xxx@
break @xxx
fun main(){
myloop@ for(ch in 'A'..'C'){
for (n in 1..4){
println("ch andn")
if(n==2)
break @myloop
}
}
}
标准库
集合
概述
集合接口相关函数位于 ktolin.collections
包中,Kotlin相关的集合类型包含有:List
(有序集合),Set
(唯一集合),Map
(key-value键值对)。
集合的构造
创建集合最常用的办法是使用过标准库函数:listOf<T>()
、setOf<T>()
、mutableListOf<T>()
、mutableSetOf<T>()
。如果是以逗号分割的集合元素列表作为参数,编译器会自动检测元素的类型。创建空集合时,必须明确指定类型。
listOf<T>()
、setOf<T>()
、mapOf<T>()
只读,提供元素访问的操作- 当修改时编译器会报错:
No set method providing array access
(没有提供数组访问的设置方法)
- 当修改时编译器会报错:
mutableListOf<T>()
、mutableListOf<T>()
、mutableMapOf<T>()
可变,提供添加、删除,更新其元素的操作
var numberSet = setOf("one","two")
var emptySet = mutableSetOf<String>()
Map也有同样的函数:mapOf() 与 mutableMapOf()
var numbersMap = mapOf("k1" to 1,"k2" to 2)
映射的键和值作为Pair
对象传递,通常使用中缀函数to创建:to 符号创建一个短时存活的Pair对象,性能会受影响,可以创建可以写Map
并使用apply()
函数来保持初始化的流畅。
var numbersMap = mutableMapOf<String,String>().apply {
this["k1"] = "1";
this["k2"] = "2"
}
buildList
、buildSet
、buildMap
也可以快速构造集合
val list = buildList<String> { add("one"); add("two") }
println(list)
val set = buildSet<String> { add("one"); add("two") }
println(set)
val map =buildMap<String, String> { put("a", "1"); put("b", "2") }
println(map)
空集合
emptyList()
、emptySet()
、emptyMap()
创建空集合时,应指定集合将包含的元素类型。
val empty = emptyList<String>()
复制
要创建与现有集合具有相同元素的集合,可以使用复制的操作。可以使用toList()
、toMutableList()
、toSet()
等。创建了集合的快照,结果是创建了一个具有相同元素的新集合,如果在源集合中添加或删除元素,则不会影响副本,副本也可以独立于源集合进行更改。
toList
复制出一个readOnly
toMutableList
复制出一个可以添加,删除,编辑的集合
fun main() {
val sourceList = mutableListOf("1", "2", "3", "4", "5")
val copySourceList = sourceList.toMutableList()
println("source:" + sourceList)
println("copy object:" + copySourceList)
println("---------------")
sourceList.add("6")
println("source:" + sourceList)
println("copy object:" + copySourceList)
println("---------------")
copySourceList.add("7")
println("source:" + sourceList)
println("copy object:" + copySourceList)
}
source:[1, 2, 3, 4, 5]
copy object:[1, 2, 3, 4, 5]
---------------
source:[1, 2, 3, 4, 5, 6]
copy object:[1, 2, 3, 4, 5]
---------------
source:[1, 2, 3, 4, 5, 6]
copy object:[1, 2, 3, 4, 5, 7]
迭代器
Iterable<T>
接口的继承者(包括Set
和List
)可以通过调用iterator()
函数获得迭代器。一旦获得迭代器它就指向集合的第一个元素;调用next()
函数将返回此元素,并将迭代器指向下一个元素(如果下一个元素存在)。一旦迭代器通过了最后一个元素,它就不能再用于检索元素,也无法重新指向到以前的任何位置,要再次遍历集合,请创建一个新的迭代器。
fun main(){
val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
println(numbersIterator.next())
}
}
遍历 Iterable
集合的另一种方法只for
循环。
fun main(){
val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
println(item)
}
}
forEeach
fun main() {
val numbers = listOf("one", "two", "three", "four")
numbers.forEach {
println(it)
}
}
可变迭代器
为了迭代可变集合,于是有了 [MutableIterator](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-iterator/index.html)
来扩展 Iterator
使其具有元素删除函数 [remove()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-iterator/remove.html)
。因此,可以在迭代时从集合中删除元素。
fun main() {
val numbers = mutableListOf("one", "two", "three", "four")
val mutableIterator = numbers.mutableIterator()
mutableIterator.next()
mutableIterator.remove()
println("After removal: $numbers")
}
[one, two, three, four]
区间与数列
Kotlin 可通过调用 kotlin.ranges 包中的 rangeTo函数以及操作符形式的…轻松的创建两个值的区间。
- i in 1…4 等同于 i >=1 && i <= 4
fun main(){
for (i in 1..4)
println(i)
}
1,2,3,4
- 如果要反向迭代数字,请使用 downTo 函数
fun main(){
for (i in 4 downTo 1)
println(i)
}
4,3,2,1
- 默认通过任意步长(不一定为1)迭代数字,请使用step函数
fun main() {
for (i in 1..8 step 2)
println(i)
}
1,3,5,7
fun main(){
for (i in 10 downTo 1 step 3)
println(i)
}
10,7,3,1
- 迭代不包含结束元素,请使用 until 函数
fun main(){
for (i in 1 until 5)
println(i)
}
1,2,3,4
集合的操作
Ktolin 标准库提供了用于对集合执行操作的多种函数,这包括简单的操作,例如获取、添加元素,以及更复杂的操作,包括搜索,排序,过滤,转换等。
集合转换
Kotlin 标准库为集合转换提供一组扩展函数,这些函数根据提供的转换规则从现有的集合中构建新的集合。
映射
map
映射转换从另一个集合的元素上的函数结果创建一个集合,基本的映射函数是map(),它将给定的lambda函数应用于每个后续元素,并返回lambda结果列表,结果的顺序与元素的原始顺序相同。如需应用还要用到元素索引作为参数的转换,请使用 mapIndexed()
fun main() {
val list = listOf(1, 2, 3, 4, 5)
val mapList = list.map { it -> it + 1 }
println(mapList) // [2, 3, 4, 5, 6]
mapList.mapIndexed { idx, it ->
println("下标:$idx:元素值:$it")
}
// 下标:0:元素值:2
// 下标:1:元素值:3
// 下标:2:元素值:4
// 下标:3:元素值:5
// 下标:4:元素值:6
}
mapNotNull
如果在转换某些元素上产生null值,则可以通过mapNotNull() 函数来取代
fun main(){
val listOfNull = listOf(1, 2, 3, 4, 5, 6)
val listOfNullMap = listOfNull.mapNotNull { it -> if(it%2 ==0 ) null else it + 100}
println(listOfNullMap) // [101, 103, 105]
}
mapKeys / mapValues
Map集合映射转换时,有两个选择, 转换键,使值保持不变,反之亦然。
转换键 : mapKeys
转换值:mapValues
fun main() {
val map = buildMap<String, Int> {
put("k1", 1)
put("k2", 2)
put("k3", 3)
put("k4", 5)
}
// 将key的值统一大写
val keyUppercaseMap = map.mapKeys { item -> item.key.uppercase() }
println(keyUppercaseMap) // {K1=1, K2=2, K3=3, K4=5}
// 将value的值乘以2
val valueDoubleMap = map.mapValues { item -> item.value * 2 }
println(valueDoubleMap) // {k1=2, k2=4, k3=6, k4=10}
}
双路合并
zip
双路合并转换时根据两个集合中具有相同位置的元素构建配对。通过 zip 扩展函数完成。在一个集合(或数组)上以另一个集合(或数组)作为参数调用,zip函数返回Pair对象的列表。如果集合的大小不同,则zip() 函数的结果为较小集合的大小;结果中不包含较大集合的后续元素,zip()也可以中缀形式调用 a zip b.
fun main() {
val colors = listOf("red", "brown", "grey")
val animals = listOf("fox", "bear", "wolf")
val zipData = colors zip animals
println(zipData) // [(red, fox), (brown, bear), (grey, wolf)]
for ((color, animal) in zipData) {
println("The $color $animal is very fast.")
}
}
- 如果集合中元素大小不匹配,则返回小的集合匹配结果
fun main(){
val colors1 = listOf("red", "brown", "grey")
val animals1 = listOf("fox", "bear")
val zipData1 = colors1 zip animals1
println(zipData1) // [(red, fox), (brown, bear)]
}
unzip
如果要分割键值对列表,请调用 unzip
fun main(){
val numberPairs = listOf("one" to 1, "two" to 2, "three" to 3, "four" to 4)
println(numberPairs.unzip()) // ([one, two, three, four], [1, 2, 3, 4])
}
关联
associateWith
基本的关联函数 associateWith 创建一个map,其中原始集合的元素是键,并通过给定的转换函数从中产生值。
fun main() {
val numbers = listOf("one", "two", "three", "four")
val numbersMap = numbers.associateWith { it.length }
println(numbersMap) // {one=3, two=3, three=5, four=4}
}
associateBy
为了使用集合元素作为值来构建Map,请使用函数 associateBy()
fun main(){
val numbersMap1 = numbers.associateBy { it -> it.first().uppercase() }
println(numbersMap1) // {O=one, T=three, F=four}
}
associate
另外一种构建Map的方法是使用函数 associate(), 其中Map键和值都是通过集合元素生成的,他需要一个lambda函数,该函数返回的Pair:键和相应Map条目的的值
注意:该函数会生成临时的Pair对象,可能会影响性能。
fun main(){
val fullNameList = listOf("Alice Adams", "Brian Brown", "Clara Campbell")
val fullNameListMap = fullNameList.associate { name -> name.split(" ")[0]
.let { it to name.split(" ")[1] } }
println(fullNameListMap) // {Alice=Adams, Brian=Brown, Clara=Campbell}
}
打平
flatten
如需操作嵌套的集合,可以在一个集合的集合(一个Set组成的List)上调用它,该函数可以返回嵌套集合中的所有元素的一个List。
fun main(){
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
val flatten = numberSets.flatten()
println(flatten) // [1, 2, 3, 4, 5, 6, 1, 2]
}
flatMap
该函数也提供一种灵活的方式来处理嵌套的集合,它需要一个函数将一个集合元素映射到另一个集合,因此flatMap返回单个列表其中包含所有的元素值,所以 flatMap 表现为map与flatten的连续调用。
fun main(){
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
val flatMap = numberSets.flatMap { it }
println(flatMap) // [1, 2, 3, 4, 5, 6, 1, 2]
}
字符串表示
joinToString
joinToString函数根据提供的参数从集合元素构建单个String.
fun main() {
val numbers = listOf("he", "llo", "w", "orld")
val numbersStr = numbers.joinToString()
println(numbersStr) // he, llo, w, orld
}
要构建自定义字符串表示形式,可以在函数参数 separator
、prefix
与 postfix
中指定其参数。 结果字符串将以 prefix
开头,以 postfix
结尾。除最后一个元素外,separator
将位于每个元素之后。
fun main() {
val numbers = listOf("one", "two", "three", "four")
// start: one | two | three | four: end
println(numbers.joinToString(separator = " | ", prefix = "start: ", postfix = ": end"))
}
对于较大的集合,可能需要指定 limit
——将包含在结果中元素的数量。 如果集合大小超出 limit
,所有其他元素将被 truncated
参数的单个值替换。
fun main() {
val numbers = (1..100).toList()
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, <...>
println(numbers.joinToString(limit = 10, truncated = "<...>"))
}
最后,要自定义元素本身的表示形式,请提供 transform
函数
fun main() {//sampleStart
val numbers = listOf("one", "two", "three", "four")
// Element: ONE, Element: TWO, Element: THREE, Element: FOUR
println(numbers.joinToString { "Element: ${it.toUpperCase()}"})
}
joinTo
执行相同的操作,但将结果附加到给定的 Appendable对象
fun main(){
val numbers2 = listOf("one", "two", "three", "four")
val listString = StringBuffer("The list of numbers: ")
numbers2.joinTo(listString)
println(listString) // The list of numbers: one, two, three, four
}
过滤
过滤条件由谓词定义-接受一个集合元素并且返回布尔值的lambda表达式,其返回值含义:true说明给定元素与谓词匹配,false 则表示不匹配。
filter
filter() 返回与其匹配的集合元素,对于List和Set,过滤结果都是一个List,对Map来讲结果还是Map。
fun main() {
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter { it.length > 3 }
// [three, four]
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 }
// {key11=11}
println(filteredMap)
}
filter()中谓词只能检查元素的值,如果想在过滤中使用元素在集合中的位置,应该使用filterIndexed(),他接受一个带有两个参数的谓词:元素的索引和元素的值。
filterNot
如果想使用否定条件来过滤集合,请使用 filterNot . 它返回一个让谓词产生false的元素列表
fun main() {
val numbers = listOf("one", "two", "three", "four")
val filteredIdx = numbers.filterIndexed { index, s -> (index != 0) && (s.length < 5) }
val filteredNot = numbers.filterNot { it.length <= 3 }
// [two, four]
println(filteredIdx)
// [three, four]
println(filteredNot)
}
filterIsInstance
过滤给定类型的元素
fun main() {
val numbers = listOf(null, 1, "two", 3.0, "four")
// TWO FOUR
numbers.filterIsInstance<String>().forEach {
println(it.uppercase())
}
}
filterNotNull
返回所有的非空元素
fun main() {
val numbers = listOf(null, "one", "two", null)
val numberNotNullList = numbers.filterNotNull();
// [one, two]
println(numberNotNullList)
}
划分
partiton
另一个过滤函数 – [partition()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/partition.html)
– 通过一个谓词过滤集合并且将不匹配的元素存放在一个单独的列表中。因此,你得到一个 List
的 Pair
作为返回值:第一个列表包含与谓词匹配的元素并且第二个列表包含原始集合中的所有其他元素。
fun main() {
val numbers = listOf("one", "two", "three", "four")
val (match, rest) = numbers.partition { it.length > 3 }
println(match) // [three, four]
println(rest) // [one, two]
}
校验谓词
any
如果至少有一个元素匹配给定的谓词,那么any()返回true
none
如果没有元素与给定谓词匹配,那么none()返回true
all
如果所有的元素都匹配给定谓词,那么all()返回true,在一个空集合上使用任何有效的谓词去调用all()都会返回true
fun main() {
val numbers = listOf("one", "two", "three", "four")
println(numbers.any { it.endsWith("e") }) // true
println(numbers.none { it.endsWith("a") }) // true
println(numbers.all { it.endsWith("e") }) // false
println(emptyList<Int>().all { it > 5 }) // true
}
加减操作符
在kotlin中,为集合定义了plus(+) 和minus(-)操作符;
- plus 的结果包含原始集合 和 第二个操作数中的元素
- minus 的结果包含原始集合中的元素,但第二个操作数中的元素 除外
fun main() {
val numbers = listOf("one", "two", "three", "four")
val plusList = numbers + "five"
val plusList2 = plusList.plus("six")
// [one, two, three, four, five, six]
println(plusList2)
val minusList = numbers - listOf("three", "four")
// [one, two]
println(minusList)
}
分组
Kotlin 标准库提供用于对集合元素进行分组的扩展函数。 基本函数 [groupBy()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/group-by.html)
使用一个 lambda 函数并返回一个 Map
。 在此 Map 中,每个键都是 lambda 结果,而对应的值是返回此结果的元素 List
还可以使用第二个 lambda 参数(值转换函数)调用 groupBy()
。 在带有两个 lambda 的 groupBy()
结果 Map 中,由 keySelector
函数生成的键映射到值转换函数的结果,而不是原始元素
groupBy
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
// {O=[one], T=[two, three], F=[four, five]}
println(numbers.groupBy { it.first().uppercase() })
// {o=[ONE], t=[TWO, THREE], f=[FOUR, FIVE]}
println(numbers.groupBy(keySelector = { it.first() }, valueTransform = { it.uppercase() }))
}
eachCount
分组后计算每个组中的元素
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
// {o=1, t=2, f=2, s=1}
println(numbers.groupingBy { it.first() }.eachCount())
}
取集合的一部分
slice
[slice()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/slice.html)
返回具有给定索引的集合元素列表。 索引既可以是作为区间传入的也可以是作为整数值的集合传入的。
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
// [two, three, four]
println(numbers.slice(1..3))
// [one, three, five]
println(numbers.slice(0..4 step 2))
// [four, six, one]
println(numbers.slice(setOf(3, 5, 0))) // 第3/5/0 索引下元素
}
take
从头获取指定数量元素
takeLast
从尾获取指定数量元素
drop
从头去除给定数量元素
dropLast
从尾去除给定数量的元素
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
// [one, two, three]
println(numbers.take(3))
// [four, five, six]
println(numbers.takeLast(3))
// [two, three, four, five, six]
println(numbers.drop(1))
// [one]
println(numbers.dropLast(5))
}
chunked
将集合分解为给定大小的块,chunked()
采用一个参数(块的大小),并返回一个 List
其中包含给定大小的 List
fun main() {
val numbers = (0..13).toList()
// [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13]]
println(numbers.chunked(3))
}
windoed
可以检索给定大小的集合元素中所有可能区间。 获取它们的函数称为 [windowed()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/windowed.html)
: 它返回一个元素区间列表,比如通过给定大小的滑动窗口查看集合,则会看到该区间。 与 chunked()
不同,windowed()
返回从_每个_集合元素开始的元素区间(窗口)。 所有窗口都作为单个 List
的元素返回。
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
// [[one, two, three], [two, three, four], [three, four, five]]
println(numbers.windowed(3))
}
取单个元素
按位置取
elementAt
为了检索特定位置的元素,有一个函数 [elementAt()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/element-at.html)
。 用一个整数作为参数来调用它,你会得到给定位置的集合元素。 第一个元素的位置是 0
,最后一个元素的位置是 (size - 1)
。
elementAt()
对于不提供索引访问或非静态已知提供索引访问的集合很有用。 在使用 List
的情况下,使用索引访问操作符 (get()
或 []
)更为习惯。
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
// four
println(numbers.elementAt(3))
// four
println(numbers.get(3))
// four
println(numbers[3])
}
elmentArOrNull
当指定位置超出集合范围,下标越时,返回null
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
// null
println(numbers.elementAtOrNull(10))
}
elementAtOrElse
当指定位置超出集合范围,下标越时,返回指定值
fun main() {
val numbers = listOf("one", "two", "three", "four", "five")
// hello
println(numbers.elementAtOrElse(10) { "hello" })
}
按条件取
first
last
函数 [first()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/first.html)
和 [last()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/last.html)
还可以让你在集合中搜索与给定谓词匹配的元素。 当你使用测试集合元素的谓词调用 first()
时,你会得到对其调用谓词产生 true
的第一个元素。 反过来,带有一个谓词的 last()
返回与其匹配的最后一个元素。
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
// three
println(numbers.first { it.length > 3 }) // 第一个长度>3的元素
// five
println(numbers.last { it.startsWith("f") }) // 最后一个以f开头的元素
}
如果没有元素与谓词匹配,两个函数都会抛出异常,为了避免异常,可以使用 firstOrNull() 与 laseOrNull() 如果找不到匹配的元素,它们将返回null。
- 使用 find 代替firstOrNull
- 使用 findLast 代替 lastOrNull
fun main() {
val numbers = listOf(1, 2, 3, 4)
// null
println(numbers.find { it % 6 == 0 })
// 4
println(numbers.findLast { it % 2 == 0 })
}
随机取元素
random
如果需要检索集合的一个随机元素,那么请调用 [random()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/random.html)
函数。 你可以不带参数或者使用一个 [Random](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/-random/index.html)
对象作为随机源来调用它。
fun main() {
val numbers = listOf(1, 2, 3, 4)
println(numbers.random())
}
检测元素是否存在
如需检查集合中某个元素的存在,可以使用 contains() 函数。 如果存在一个集合元素等于(equals())函数参数,那么它返回 true。 你可以使用 in 关键字以操作符的形式调用 contains()。 如需一次检查多个实例的存在,可以使用这些实例的集合作为参数调用 containsAll()。
contains
fun main() {
val numbers = listOf("one", "two", "three", "four", "five", "six")
// true
println(numbers.contains("four"))
}
排序
自然排序
- sorted 升序
- sortedDescending 降序
fun main() {
val numbers = listOf(1, 80, 30, 3)
// Sorted ascending: [1, 3, 30, 80]
println("Sorted ascending: ${numbers.sorted()}")
// Sorted descending: [80, 30, 3, 1]
println("Sorted descending: ${numbers.sortedDescending()}")
}
自定义排序
- sortedBy
- _sortedByDescending _
fun main() {
val numbers = listOf("one", "two", "three", "four")
val sortedNumbers = numbers.sortedBy { it.length }
// Sorted by length ascending: [one, two, four, three]
println("Sorted by length ascending: $sortedNumbers")
val sortedByLast = numbers.sortedByDescending { it.last() }
// Sorted by the last letter descending: [four, two, one, three]
println("Sorted by the last letter descending: $sortedByLast")
}
反转
可以使用 [reversed()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reversed.html)
fun main() {
val numbers = listOf("one", "two", "three", "four")
// [four, three, two, one]
println(numbers.reversed())
}
随机排序
[shuffled()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/shuffled.html)
函数返回一个包含了以随机顺序排序的集合元素的新的 List
fun main() {
val numbers = listOf("one", "two", "three", "four")
println(numbers.shuffled())
}
聚合操作
Kotlin 集合包含用于常用的 聚合操作 (基于集合内容返回单个值的操作)的函数
[minOrNull()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/min-or-null.html)
与[maxOrNull()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/max-or-null.html)
分别返回最小和最大的元素。[average()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/average.html)
返回数字集合中元素的平均值。[sum()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sum.html)
返回数字集合中元素的总和。[count()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/count.html)
返回集合中元素的数量。
fun main() {
val numbers = listOf(6, 42, 10, 4)
println("Count: ${numbers.count()}")
println("Max: ${numbers.maxOrNull()}")
println("Min: ${numbers.minOrNull()}")
println("Average: ${numbers.average()}")
println("Sum: ${numbers.sum()}")
}
Count: 4
Max: 42
Min: 4
Average: 15.5
Sum: 62
归集
对于更特定的情况,有函数 [reduce()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce.html)
和 [fold()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fold.html)
,它们依次将所提供的操作应用于集合元素并返回累积的结果。 操作有两个参数:先前的累积值和集合元素。
这两个函数的区别在于:fold()
接受一个初始值并将其用作第一步的累积值,而 reduce()
的第一步则将第一个和第二个元素作为第一步的操作参数。
fun main() {
val numbers = listOf(5, 2, 10, 4)
// 5 + 2*2 = 9 9 +10*2= 29 29 + 4*2 = 37
val sumDoubledReduce = numbers.reduce { sum, element -> sum + element * 2 }
println(sumDoubledReduce)
val sumDoubled = numbers.fold(0) { sum, element -> sum + element * 2 }
println(sumDoubled)
}
List 相关操作
按索引取元素
- get
- first
- last
- getOrElse : 提供用于计算默认值的函数,如果集合中不存在索引,则返回默认值。
- getOrNull : 返回
null
作为默认值。
取列表的一部分 subList
fun main() {
val numbers = (0..13).toList()
// [3, 4, 5]
println(numbers.subList(3, 6))
}
查找元素位置
- indexOf
- lastIndexOf
- indexOfFirst() : 返回与谓词匹配的_第一个元素的索引_,如果没有此类元素,则返回
-1
。 - indexOfLast() : 返回与谓词匹配的_最后一个元素的索引_,如果没有此类元素,则返回
-1
。
fun main() {
val numbers = mutableListOf(1, 2, 3, 4)
// 2 下标
println(numbers.indexOfFirst { it > 2})
// 2 下标
println(numbers.indexOfLast { it % 2 == 1})
}
添加
- add
- addAll
fun main(){
val numbers = mutableListOf("one", "five", "six")
numbers.add(1, "two")
numbers.addAll(2, listOf("three", "four"))
println(numbers)
}
更新
- set
- 操作符形式 []
fun main() {
val numbers = mutableListOf("one", "five", "three")
numbers[1] = "two"
println(numbers)
}
- fill() 将集合中元素的值全部替换为指定值
fun main() {
val numbers = mutableListOf(1, 2, 3, 4)
numbers.fill(3)
// [3, 3, 3, 3]
println(numbers)
}
删除
- removeAt
fun main() {
val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.removeAt(1)
// [1, 3, 4, 3]
println(numbers)
}
排序
在集合排序中,描述了按特定顺序检索集合元素的操作。 对于可变列表,标准库中提供了类似的扩展函数,这些扩展函数可以执行相同的排序操作。 将此类操作应用于列表实例时,它将更改指定实例中元素的顺序。
就地排序函数的名称与应用于只读列表的函数的名称相似,但没有 ed/d
后缀:
sort*
在所有排序函数的名称中代替sorted*
:[sort()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sort.html)
、[sortDescending()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sort-descending.html)
、[sortBy()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sort-by.html)
等等。[shuffle()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/shuffle.html)
代替shuffled()
。[reverse()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reverse.html)
代替reversed()
。
[asReversed()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-reversed.html)
在可变列表上调用会返回另一个可变列表,该列表是原始列表的反向视图。在该视图中的更改将反映在原始列表中。 以下示例展示了可变列表的排序函数:
fun main() {
val numbers = mutableListOf(1, 30, 8, 55)
numbers.sort()
// [1, 8, 30, 55]
println("按升序排序: $numbers")
numbers.sortDescending()
// [55, 30, 8, 1]
println("按降序排序: $numbers")
numbers.sortBy { it % 2 }
// [30, 8, 55, 1]
println("it % 2 sorted: $numbers")
numbers.sortByDescending { it }
// [55, 30, 8, 1]
println("it % 2 sortByDescending : $numbers")
numbers.sortWith(compareBy<Int> { it }.thenBy { it })
// [1, 8, 30, 55]
println("Sort by Comparator: $numbers")
numbers.shuffle()
// [1, 30, 55, 8]
println("Shuffle: $numbers")
numbers.reverse()
// [8, 55, 30, 1]
println("Reverse: $numbers")
}
Set 相关操作
Kotlin 集合包中包含 set 常用操作的扩展函数: 找出集合间的交集、并集或差集。
并集
union函数,也能使用中缀形式使用 a union b.
fun main() {
val numbers = setOf("one", "two", "three")
// [one, two, three, four, five]
println(numbers union setOf("four", "five"))
// [four, five, one, two, three]
println(setOf("four", "five") union numbers)
}
交集
要找到两个集合(两个集合中都有的元素)的交集,请使用
intersect()
函数
fun main() {
val numbers = setOf("one", "two", "three")
// [one, two]
println(numbers intersect setOf("two", "one"))
}
差集
要找到不在另一个集合中的集合元素,请使用
subtract()
函数
fun main() {
val numbers = setOf("one", "two", "three")
// [one, two]
println(numbers subtract setOf("three", "four"))
// [one, two]
println(numbers - setOf("three", "four"))
}
计算两个集合之间的差异,并将结果合并:
fun main() {
val numbers = setOf("one", "two", "three")
val numbers2 = setOf("three", "four")
// [one, two, four]
println((numbers - numbers2) union (numbers2 - numbers))
}
Map 相关操作
取值
- get()
- [key]
- getValue()
- getOrElse()
- getOrDefault()
fun main() {
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.get("one"))
println(numbersMap["one"])
println(numbersMap.getOrDefault("four", 10))
println(numbersMap["five"]) // null
//numbersMap.getValue("six") // exception!
}
要对 map 的所有键或所有值执行操作,可以从属性 keys
和 values
中相应地检索它们。 keys
是 Map 中所有键的集合, values
是 Map 中所有值的集合。
fun main() {
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
// [one, two, three]
println(numbersMap.keys)
// [1, 2, 3]
println(numbersMap.values)
}
过滤
可以使用 [filter()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter.html)
函数来过滤 map 或其他集合。 对 map 使用 filter()
函数时, Pair
将作为参数的谓词传递给它。 它将使用谓词同时过滤其中的键和值。
fun main() {
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}
// {key11=11}
println(filteredMap)
}
还有两种用于过滤 map 的特定函数:按键或按值。 这两种方式,都有对应的函数: [filterKeys()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-keys.html)
和 [filterValues()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-values.html)
。 两者都将返回一个新 Map ,其中包含与给定谓词相匹配的条目。 filterKeys()
的谓词仅检查元素键, filterValues()
的谓词仅检查值。
fun main() {
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
val filteredKeysMap = numbersMap.filterKeys { it.endsWith("1") }
val filteredValuesMap = numbersMap.filterValues { it < 10 }
// {key1=1, key11=11}
println(filteredKeysMap)
//{key1=1, key2=2, key3=3}
println(filteredValuesMap)
}
加减操作符
由于需要访问元素的键,[plus](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/plus.html)
(+
)与 [minus](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/minus.html)
(-
)运算符对 map 的作用与其他集合不同。 plus
返回包含两个操作数元素的 Map
:左侧的 Map 与右侧的 Pair 或另一个 Map 。 当右侧操作数中有左侧 Map
中已存在的键时, 该条目将使用右侧的值。
fun main() {
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
// {one=1, two=2, three=3, four=4}
println(numbersMap + Pair("four", 4))
// {one=10, two=2, three=3}
println(numbersMap + Pair("one", 10))
// {one=11, two=2, three=3, five=5}
println(numbersMap + mapOf("five" to 5, "one" to 11))
}
写操作
- put
- putAll
其参数可以是Map或一组Pair
fun main() {
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap.putAll(setOf("four" to 4, "five" to 5))
// {one=1, two=2, three=3, four=4, five=5}
println(numbersMap)
}
删除条目
- Remove 如果同时指定键和值,则仅当键值都匹配时,才会删除此的元素。
fun main() {
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap.remove("one")
// {two=2, three=3}
println(numbersMap)
numbersMap.remove("three", 4) //不会删除任何条目
// {two=2, three=3}
println(numbersMap)
}
使用 -= 操作也可以用于可变map
fun main() {
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
// {one=1, three=3}
numbersMap -= "two"
println(numbersMap)
numbersMap -= "five" //不会删除任何条目
// {one=1, three=3}
println(numbersMap)
}
作用域函数
Kotlin 提供一组强大的作用域函数,用于简化对象的操作和管理,这些函数包括 let 、run 、with、apply和also。它们的主要区别在于上下文对象的引用方式和返回值不同
上下文对象
- this
run、with、以及apply通过关键字将上下文对象引用为lambda表达式的接受者。因此,在它们的lambda表达式中可以像在普通的类函数一样访问上下文对象。
data class Person(var name: String, var age: Int = 0, var city: String = "")
val adam = Person("Adam").apply {
age = 20 // 同 this.age = 20
city = "London"
}
- it
像let 及 also将上下文对象引用为lambda表达式参数,如果没有指定参数名,对象可以用隐式默认名称it访问。
fun getRandomInt(): Int {
return Random.nextInt(100).also {
println("value $it")
}
}
返回值
根据返回结果,作用域函数可以分为以下两类
- apply、also 返回上下文对象
- let 、run 、 with 返回lambda表达式的结果
let
用途: 适用于对非空对象执行某些操作,或者在链式调用中转换结果
上下文对象:it
返回值:lambda表达式的结果
使用场景:
- 链式调用中处理非空结果
- 执行某些操作并返回一个新的结果
val str = "Hello, World!"
val length = str.let {
println(it) // 输出: Hello, World!
it.length
}
println(length) // 输出: 13
run
用途:用于初始化或配置对象,或者执行一系列操作并返回计算结果
上下文:使用this引用
返回值:lambda表达式的结果
使用场景:
- 初始化或配置复杂对象
- 执行多步计算并返回最终结果
val result = "Hello".run {
println(this) // 输出: Hello
length
}
println(result) // 输出: 5
with
用途:用于对同一个对象执行多次操作,通常用于对象的配置
上下文:使用this引用
返回值:lambda表达式的结果
使用场景:
- 对单个对象执行多个操作
- 配置复杂对象时提高代码可读性
val builder = StringBuilder()
val result = with(builder) {
append("Hello, ")
append("World!")
toString()
}
println(result) // 输出: Hello, World!
apply
用途:用于配置对象属性,常用构建器模式
上下文:使用this引用
返回值: 上下文对象本身
使用场景:
- 初始化或设置对象属性时保持流畅的 API 调用风格
- 配置新创建的实例
val person = Person().apply {
name = "John"
age = 30
}
println(person) // 输出: Person(name=John, age=30)
also
用途:用于在链式调用中执行额外操作,不修改原始数据
上下文:使用it引用
返回值: 上下文对象本身
使用场景:
- 在不改变原始数据结构的情况下记录日志或调试信息。
- 在链式调用中添加副作用操作(例如打印日志)
val numbers = mutableListOf("one", "two", "three")
numbers.also { println("Original list: $it") }
.add("four")
println(numbers)
// Original list: [one, two, three]
// [one, two, three, four]
takeIf / takeUnless
用于条件判断的扩展函数,它们可以帮助你根据条件选择性地返回对象本身或null,从而简化代码中条件逻辑。
- takeIf
用途:当对象满足给定的条件时,返回该对象,否则返回null
val number = 10
val result = number.takeIf { it > 5 }
println(result) // 输出: 10,因为条件 it > 5 为 true
val nullResult = number.takeIf { it < 5 }
println(nullResult) // 输出: null,因为条件 it < 5 为 false
- takeUnless
用途:当对象不满足给定条件时,返回该对象,否则返回null
val number = 10
val result = number.takeUnless { it < 5 }
println(result) // 输出: 10,因为条件 it < 5 为 false
val nullResult = number.takeUnless { it > 5 }
println(nullResult) // 输出: null,因为条件 it > 5 为 true
时间度量
kotlin的Duration类是用于表示时间间隔的一个强大工具,它提供了多种方法来创建,操作和格式化时间间隔。
创建时间
import kotlin.time.*
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.days
fun main() {
val fiveHundredMilliseconds: Duration = 500.milliseconds
val zeroSeconds: Duration = 0.seconds
val tenMinutes: Duration = 10.minutes
println(fiveHundredMilliseconds) // 500ms
println(zeroSeconds) // 0s
println(tenMinutes) // 10m
}
也可以使用Duration对象执行基本的算术运算
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds
fun main() {
val fiveSeconds: Duration = 5.seconds
val thirtySeconds: Duration = 30.seconds
println(fiveSeconds + thirtySeconds)// 35s
println(thirtySeconds - fiveSeconds)// 25s
println(fiveSeconds * 2)// 10s
println(thirtySeconds / 2) // 15s
println(thirtySeconds / fiveSeconds)// 6.0
println(-thirtySeconds)// -30s
println((-thirtySeconds).absoluteValue)// 30s
}
获取字符串表现形式
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit
fun main() {
println(5887.milliseconds.toString(DurationUnit.SECONDS, 2))
// 5.89s
}
转换持久时间
要将您的 转换Duration
为不同的DurationUnit
,请使用以下属性:
inWholeNanoseconds
inWholeMicroseconds
inWholeSeconds
inWholeMinutes
inWholeHours
inWholeDays
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
fun main() {
val thirtyMinutes: Duration = 30.minutes
println(thirtyMinutes.inWholeSeconds)// 1800
}
DurationUnit
或者,您可以在以下扩展函数中使用您想要的作为函数参数:
.toInt()
.toDouble()
.toLong()
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
fun main() {
println(270.seconds.toDouble(DurationUnit.MINUTES))
// 4.5
}
比较持续时间
使用运算符: == 、< 、>
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
fun main() {
val thirtyMinutes: Duration = 30.minutes
val halfHour: Duration = 0.5.hours
println(thirtyMinutes == halfHour)// true
println(3000.microseconds < 25000.nanoseconds) // false
}