一、区间
1.1、区间定义
/*------------定义1到100区间------------*/
val a = 1..100//[1,100]
val b = 1 until 100 //[1,100)
val c = 1.rangeTo(100)//[1,100]
val d = IntRange(1, 100)//[1,100]
/*------------长整型区间------------*/
val a1 = 1L..100L
val b1 = 1L until 100L
val c1 = 1L.rangeTo(100L)
val d1 = LongRange(1L, 100L)
/*------------字符区间------------*/
val a2 = 'a'..'b'
val b2 = 'a' until 'b'
val c2 = 'a'.rangeTo('b')
val d2 = CharRange('a', 'b')
val aa='你'..'我'
1.2、区间获取值
val a=1.rangeTo(10)
//区间的第一个值
println(a.first)//1
//区间的最后一个值
println(a.last)//10
1.3、区间遍历
val a = 20..30
for (i in a) {
println(i)
}
/*-----------------------for循环------------------*/
//不带角标
for (i in a) {
println(i)
}
//带角标
for ((i, withIndex) in a.withIndex()) {
println("$i-----$withIndex")
}
/*-----------------------forEach循环------------------*/
//不带角标
a.forEach {
println(it)
}
//带角标
a.forEachIndexed { index, i ->
println("$index-----$i")
}
1.4、反向区间和区间的反转
/*----------------------- 反向区间 -----------------------*/
//定义10到1的区间
val s=10 downTo 1
s.forEach {
println(it)
}
/*----------------------- 区间反转 -----------------------*/
val a=1..10
//区间反转
val reversed = a.reversed()
reversed.forEach {
println(it)
}
1.5、区间设置步长
//步长必须>=0. 设置区间步长为4 打印结果为 1 5 9
val a=1..10 step 4
for (i in a) {
println(i)//1 5 9
}
二、数组
2.1、数组的定义
/*----------定义数组并赋值------------*/
val arrayOf = arrayOf("1", "N", "0", "Y")
var arrayOf1 = arrayOf(1, 2, 3)
var arrayOf2 = arrayOf("1", 2, 'a')
/*-------- 8种基本数组类型数组 -----------*/
//定义Int数组
val s0 = IntArray(10)
//定义Int数组并赋值
val s1 = IntArray(10) {
1//把数组里面每一个元素都初始化为1
}
// IntArray
// BooleanArray
// LongArray
// DoubleArray
// FloatArray
// ShortArray
// ByteArray
// CharArray
2.2、数组打印
val a= arrayOf("1","A","B")
//打印数组,默认以","分隔
println(a.joinToString())//1, A, B
//打印数组,以"、"分隔 开始增加"【" 结束增加 "】"
println(a.joinToString(separator = "、",prefix = "[",postfix = "]"))//[1、A、B]
//数组转字符串
println(a.joinToString(""))//1AB
2.3、数组的遍历
val a = arrayOf("你", "我", "他")
/*----------for循环----------*/
//不带角标
for (s in a) {
println(s)
}
//带角标
for ((index, s) in a.withIndex()) {
println("$index----$s")
}
/*----------forEach循环----------*/
//不带角标
a.forEach {
println(it)
}
//带角标
a.forEachIndexed { index, s ->
println("$index----$s")
}
2.4、数组元素的修改
val s = arrayOf(100, 102, 104)
//把第0位改为121
s[0] = 121
//把第1位改为110
s.set(1, 110)
s.forEach{
println(it)
}
2.5、数组元素角标的查找
val a = arrayOf("张三", "李四", "王五", "李四", "赵六")
/*------------普通方法查找-----------*/
//查找第一个 "李四" 的角标
println(a.indexOf("李四"))//1 返回第一个对应的元素角标 如果没有找到返回-1
//查找最后一个 "李四" 的角标
println(a.lastIndexOf("李四"))//3
/*------------高阶函数实现-----------*/
//查找第一个 姓 "李" 的角标
val index = a.indexOfFirst {
it.startsWith("李")
}
println(index)//1
//查找最后一个 "李四" 的角标
val index2 = a.indexOfLast {
it=="李四"
}
println(index2)//3
2.6、数组切片(slice、sliceArray)
//数组切片
val b= intArrayOf(5,2,0,1,3,1)
//截取指定范围数据集合(返回是集合)
val slice = b.slice(2..5)
println(slice)//[0, 1, 3, 1]
//截取指定范围数据数组(返回是数组)
val sliceArray = b.sliceArray(2..5)
println(sliceArray.joinToString())//0, 1, 3, 1
2.7、二维数组及多维数组
//二维数组定义
val array = Array(2) { IntArray(2) }
//给数据赋值
array[0][0]=1
array[0][1]=2
//遍历数组
for ((i,ints) in array.withIndex()) {
for ((j,int) in ints.withIndex()) {
println("i=$i,j=$j,int=$int")
}
}
// i=0,j=0,int=1
// i=0,j=1,int=2
// i=1,j=0,int=0
// i=1,j=1,int=0
//三维数组定义
val arrB = Array(3){Array(3){IntArray(3)}}
//三维数组赋值
arrB[0][0][0]=1
arrB[0][0][1]=2
//遍历三维数组
for (one in arrB) {
for (two in one) {
for (three in two) {
println(three)
}
}
}
三、函数
3.1、函数定义
//无参无返回值
fun sayHello() {//返回值
println("hello")
}
//有参无返回值
fun sayHello(name: String) {
println("hello " + name)
}
//有参有返回值
fun getLength(name: String): Int {
return name.length
}
//无参有返回值
fun getHello(): String {
return "hello"
}
3.2、顶层函数
Kotlin中的顶层函数反编译成的Java中的容器类名一般是顶层文件名+“Kt”后缀作为类名,但是也是可以自定义的。也就是说顶层文件名和生成容器类名没有必然的联系。通过Kotlin中的@file: JvmName(“自定义生成类名”)注解就可以自动生成对应Java调用类名,注意需要放在文件顶部,在package声明的前面
//生成Java调用类名,放在文件顶部,在package声明的前面
@file: JvmName("Util")
package com.zp.kotlin
//函数式编程 函数式一等公民 函数可以独立于对象单独存在
//顶层函数
fun helloWord() {
}
3.3、嵌套函数
//顶层函数
fun main(args: Array<String>) {
//嵌套函数
fun hello() {
println("hello")
}
hello()
}
3.4、函数表达式
println(add(1, 1))//2
println(add2(1, 1))//2
println(add3(1, 1))//2
fun add(m: Int, n: Int): Int {
return m + n
}
//函数体只有一行代码 可以省略{} 省略return 用=连接
fun add2(m: Int, n: Int): Int = m + n
//函数体只有一行代码 可以省略{} 省略return 用=连接 返回值类型也不用写
fun add3(m: Int, n: Int) = m + n
3.5、函数表达式补充
/*------------------ 函数引用:: ------------------*/
val a = ::add5
println(a(1, 1))//2
println(a?.invoke(1, 1))//2 可以处理函数变量为空的情况下调用
/*------------------- 函数变量 -------------------*/
// val b = { m: Int, n: Int -> m + n }
val b: (Int, Int) -> Int = { m, n -> m + n }匿名函数
println(b(1, 1))//2
fun add5(m: Int, n: Int): Int {
return m + n
}
3.6、默认参数和具名参数
sendRequest("http://www.baidu.com")//发送请求路径http://www.baidu.com,请求方式GET
sendRequest("http://www.baidu.com", "POST")//发送请求路径http://www.baidu.com,请求方式POST
//具名参数 参数位置可以变化
sendRequest(method = "FILE", path = "http://www.baidu.com")//发送请求路径http://www.baidu.com,请求方式FILE
fun sendRequest(path: String, method: String = "GET") {//="GET" :默认参数
println("发送请求路径$path,请求方式$method")
}
3.7、可变参数(vararg)
val adds = adds(1, 2, 3)
println(adds)
fun adds(vararg a: Int): Int {//vararg 可变参数,无论你传递多少个我都能求他们的和
//kotlin 不能直接对函数参数进行重新赋值(a=IntArray(10))
//a是一个数组类型
var s = 0
a.forEach {
s += it
}
return s
}
3.8、可变参数展开操作符(*)
val arrayOf = arrayOf("a", "bb", "ccc")
//为了将数组展开并传入可变参数,Kotlin使用星号(*)操作符将数组进行展开
test(*arrayOf)
fun test(vararg a:String){
println(a.toList())//[a, bb, ccc]
}
四、异常
4.1、处理异常
val a = 10
val b = 0
var c: Int = 0
//异常处理
try {
c = a / b
} catch (e: Exception) {
println("捕获到异常")
} finally {
println("最终要执行的代码")
}
println(c)
/**
* koltin编译时异常
* kotlin不检查编译时异常,kotlin认为大部分的编译时异常都是没有必要的
*/
val file = File("/1.txt")
val f = BufferedReader(FileReader(file))
4.2、处理异常作为函数表达式返回
//try catch 作为函数表达式
val a: Int? = try {
"abc".toInt()
} catch (e: Exception) {
null
}
println(a)//null
五、递归
5.1、递归实现
val a = 4
println("$a 的阶乘是${fact(a)}")//4 的阶乘是24
println("第$a 个斐波那契数列是${fibonacci(a)}")//第4 个斐波那契数列是3
/**
* 求n的阶乘
* 分析:n的阶乘 = n *(n-1)的阶乘 ,1的阶乘是1
*/
fun fact(n: Int): Int {
if (n == 1) {
return 1
} else {
return n * fact(n - 1)
}
}
/**
* 求n个斐波那契数列(1 1 2 3 5 8 13 21 34 55……)
* 分析:第n个斐波那契数列=第n-1个斐波那契数列+第n-2个斐波那契数列,第1个斐波那契数列是1,第2个斐波那契数列是1
*/
fun fibonacci(n: Int): Int {
if (n == 1 || n == 2) {
return 1
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
5.2、递归和迭代的对比
/**
* 常见的需求:通过迭代和递归都可以解决 复杂的问题用递归更容易实现
* StackOverflowError 递归如果递归的层级比较深容易栈内存溢出
* 递归:优点:逻辑比较简单 容易实现 缺点:容易栈内存溢出(内存开销比较大)
* 迭代:优点:内存开销小 缺点:抽象出数学模型
*/
val n = 5
println("1到$n 的和为${sum1(n)}")//1到5 的和为15
println("1到$n 的和为${sum2(n)}")//1到5 的和为15
/**
* 递归方法求和
* 求1+2+……+n的和
* 分析:1到n的和 = n+ 1到(n-1)的和 1到1的和=1
*/
fun sum1(n: Int): Int {
if (n == 1) {
return 1
} else {
return n + sum1(n - 1)
}
}
/**
* 迭代方法求和
* 求1+2+……+n的和
*/
fun sum2(n: Int): Int {
//kotlin里面参数是固定 不能修改 所以var newN = n
var newN = n
var s = 0
while (newN > 0) {
s += newN
newN--
}
return s
}
5.3、尾递归优化
/**
* 尾递归:调用了自身之后没有其他操作
* 只有是尾递归才可以做尾递归优化
*/
val n = 5
println("1到$n 的和为${sum3(n)}")//1到5 的和为15
println("1到$n 的和为${sum4(n)}")//1到5 的和为15
/**
* 原始递归求和
* 求1+2+……+n的和
* 分析:1到n的和 = n+ 1到(n-1)的和 1到1的和=1
*/
fun sum3(n: Int, result: Int = 0): Int {
if (n == 1) {
return 1
} else {
return sum3(n - 1) + n//调用自身之后做了其他操作,非尾递归
}
}
/**
* 尾递归优化求和
* 求1+2+……+n的和
* 尾递归优化步骤:
* 第一步:需要将递归转换为尾递归
* 第二步:加上tailrec
* 尾递归优化的原理:将递归转换为迭代(while循环)
*/
tailrec fun sum4(n: Int, result: Int = 0): Int {
if (n == 1) {
return result + 1
} else {
return sum4(n - 1, result + n)//调用了自身之后没有其他操作,是尾递归
}
}