day02 【Kotlin基础】
1.for循环和foreach循环
fun main(args: Array<String>) {
val str = "abc"
//普通for循环
for (c in str) {
println(c)
}
打印结果:
a
b
c
//for循环角标与值
for ((index,c) in str.withIndex()) {
println("index=$index,c=$c")
}
打印结果:
index=0,c=a
index=1,c=b
index=2,c=c
//forEach循环
str.forEach { println(it) }
打印结果:
a
b
c
//forEach循环角标与值
str.forEachIndexed { index, c ->println("index=$index,c=$c")
打印结果:
index=0,c=a
index=1,c=b
index=2,c=c
2.break和continue的使用
fun main(args: Array<String>) {
var str = "abcde"
/*-------------------------- 遍历元素:找到c就停止 -------------------------*/
for (c in str) {
if (c.equals('c'))
break
println(c)
}
打印结果:
a
b
c
/*------------------------- 遍历元素:除了c其它都打印 ---------------------*/
for (c in str) {
if(c.equals('c')){
continue
}
println(c)
}
打印结果:
a
b
d
e
3.标签处返回
fun main(args: Array<String>) {
val str1 = "abc"
val str2 = "123"
/*----------------- 找到str1和str2每一个元素组合 -------------------*/
for (c1 in str1) {
for (c2 in str2) {
println("${c1}$c2")
}
}
打印结果:
a1
a2
a3
b1
b2
b3
c1
c2
c3
-------------------- 找到b2之后就不再打印了 ---------------------
haha@for (c1 in str1) {
for (c2 in str2) {
println("${c1} $c2")
if(c1=='b'&&c2=='2'){
// break//只是跳出了内层循环 需要的是跳出外层循环
break@haha
}
}
}
打印结果:
a1
a2
a3
b1
b2
4.while和do while
fun main(args: Array<String>) {
---------------- for foreach while do while ----------------
//for和foreach 给定的数据结构,遍历里面每一个元素
//while do while 满足条件就可以执行
//求1到100数的和
var i = 1
var count = 0
while (i<=100){
count += i
i++
}
println(count)
打印结果:
5050
--------------------- do while ---------------------
var i = 1
var count = 0
do {
count += i
i++
}while (i<=100)
println(count)
打印结果:
5050
5.区间Range
任何程序的本质都是对数据的处理
区间:一段实数范围 1到100开
区间 (1,100) 不包含1和100
闭区间[1,100] 包含1和100
半开半闭区间[1,100) 包含1不包含100
a.常见区间
IntRange CharRange LongRange
定义区间的3种方式
fun main(args: Array<String>) {
----------------------- 定义区间 -----------------------
//int区间
val range1 = IntRange(1,100)//闭区间 包含1 包含100
val range2 = 1.rangeTo(100)//闭区间 包含1 包含100
val range3 = 1..100//运算符重载方式创建区间
}
b.遍历区间
fun main(args: Array<String>) {
val range = 1..100
for (i in range) {
println(i)
}
}
c.区间的反转和反向区间
fun main(args: Array<String>) {
//定义一个区间
val range1 = 1..100
/*---------------------------- 区间反转 ----------------------------*/
//反转
val range2 = range1.reversed()
//遍历
range2.forEach { println(it) }
/*---------------------------- 反向区间定义 ----------------------------*/
//通过down To 方法反转
val range2 = 100 downTo 1
//反转以后遍历
range2.forEach { println(it) }
}
6.数组
数组对于任何一门编程语言来说都是重要的数据结构之一
数组是相同数据类型元素的集合
a.数组的定义
/*------------- 定义数组:保存 张三 李四 王五 ------------*/
val arr = arrayOf("张三","李四","王五")
//创建IntArray数组 指定长度
val arr5 = IntArray(10)
//创建IntArray数组 指定元素
val arr6 = intArrayOf(1,2,3,4)
//如果不知道数组里面元素 创建一个Int数组 长度为10 每一个元素都初始化为0
val arr4 = Array<Int>(10){
0
}
b.数组元素的访问以及修改
fun main(args: Array<String>) {
val arr = arrayOf(1,2,3,4)
/*---------------------------- 访问某一个元素 ----------------------------*/
//第二个元素
val ele = arr[1]//List里面元素的访问也可以通过[]方式进行访问
println(ele)
/*---------------------------- 数组元素的修改 ----------------------------*/
//第三个元素修改为10
arr[2] = 10
println(arr[2])
arr.set(2,10)
println(arr[2])
}
c.数组角标查找
fun main(args: Array<String>) {
val arr = arrayOf("张三","李四","张四","王五","张三","赵六")
/*----------------- 查找第一个”张三”角标 -------------------------*/
val index1 = arr.indexOf("张三")
println(index1)
/*------------------ 查找最后一个”张三”角标 ----------------------*/
arr.lastIndexOf("张三")
val index2 = arr.indexOfLast {
it.equals("张三")//过滤的条件
}
println(index2)
/*------------------- 查找第一个姓”张”的人的角标-------------------*/
val index3 = arr.indexOfFirst {
it.startsWith("张")
}
println(index3)
/*----------------- 查找最后一个姓”张”的人的角标 ------------------*/
val index4 = arr.indexOfLast {
it.startsWith("张")
}
println(index4)
}
7.when表达式
fun main(args: Array<String>) {
//人 7 上小学 12 上中学 15 上高中 18 大学 社会大学
var age = 7
//需要判断当前我在干什么?
val result = todo(age)
println(result)
}
//给定的年纪在干什么事情?
//when表达式分支处理 如果只有一行可以省略{}
fun todo(age: Int): String {
when (age) {
7 -> return "开始上小学"
12 -> {
return "开始上中学"
}
15 -> {
return "开始上高中"
}
18 -> {
return "开始上大学"
}
else -> {
return "开始上社会大学"
}
}
}
a.when表达式加强
fun main(args: Array<String>) {
//人 7 上小学 12 上中学 15 上高中 18 大学 社会大学
var age = 17
//需要判断当前我在干什么?
val result = todo(age)
println(result)
}
//when表达式分支处理 如果只有一行可以省略{}
//支持的数据格式比java要多,除了java支持的6中数据格式之外可以支持区间,表达式 判断语句
fun todo(age: Int): String {
when (age) {
//通过在区间里面处理多个分支
in 1..6 -> return "没有上学"
7 -> return "开始上小学"
in 8..11 -> return "正在上小学"
12 -> {
return "开始上中学"
}
13,14->return "正在上中学"
15 -> {
return "开始上高中"
}
16,17->return "正在上高中"
18 -> {
return "开始上大学"
}
else -> {
return "开始上社会大学"
}
}
}
b.when表达式原理
* 如果是简单的when表达式 支持的6中数据格式 ,when表达式最终都会翻译成对等于Java中的switch语句
* 如果是加强的when表达式,最终会翻译成if else
c.when表达式不带参数
fun main(args: Array<String>) {
println(todo(7))
}
fun todo(age: Int): String {
when {
age==7 -> return "开始上小学"
age==12 -> {
return "开始上中学"
}
age==15 -> {
return "开始上高中"
}
age==18 -> {
return "开始上大学"
}
else -> {
return "开始上社会大学"
}
}
}
d.when表达式返回值
fun main(args: Array<String>) {
println(todo(7))
}
//如果返回when表达式必须要有else操作
//对于when表达式返回值是{}最后一行
fun todo(age: Int): Any {
return when {
age==7 -> {
"haha"
println("hello")//如果方法没有返回值,返回默认是Unit
"开始上小学"
}
age==12 -> "开始上中学"
age==15 -> "开始上高中"
age==18 -> "开始上大学"
age is Int-> "传递的是Int数据类型"
age.equals("sjdjg")-> ""
else -> "开始上社会大学"
}
8.函数表达式
a.函数表达式格式
fun main(args: Array<String>) {
val a = 10
val b = 20
//求a 加 b 的和
println(add(a, b))
}
//标准的写法
fun add(a: Int, b: Int): Int {
return a + b
//函数体只有一行,可以简写
fun add(a: Int, b: Int): Int = a + b
//智能类型推断,最终简写
fun add(a: Int, b: Int) = a + b
b.函数变量和函数引用
fun main(args: Array<String>) {
val a = 10
val b = 20
var sum = 0
/*---------------------------- 函数变量 ----------------------------*/
//padd相当于定义了函数变量
val padd:((Int,Int)->Int)? = {m,n->m+n}
//第一种调用方式
sum = padd(a,b)
//第二种方式:可以进行可空类型调用判断
padd?.invoke(a,b)
println(sum)
/*---------------------------- 函数引用 ----------------------------*/
val padd = ::add //获取函数引用 相当于c语言函数指针
//调用函数
padd(10,20)
padd.invoke(10,20)
}
c.kotlin默认参数和具名参数
fun main(args: Array<String>) {
sendRequest("GET","www.baidu.com")
//GET请求
sendRequest(path = "www.baidu.com")//具名参数
sendRequest("GET", "www.baidu.com")//具名参数
sendRequest(path = "www.baidu.com",method = "POST")//具名参数 顺序变化不影响结果
}
//项目里面大部分是GET请求 只有少部分是POST
fun sendRequest(method:String="GET",path:String){//默认参数
println("请求方式是:$method 请求路径是:$path")
}
9.可变参数
fun main(args: Array<String>) {
var a = 10
var b = 20
var c = 40
//数据不确定有多少个?
println(add(a, b,c,50,60,70,70,80,90))
}
//可变参数 数据必须是Int数据类型
fun add(vararg a:Int):Int{
//a是什么数据类型?
var count = 0
a.forEach {
count += it
}
return count
}
10.异常处理
* kotlin只有运行时异常 没有受检异常
* 无论方法有没有抛出异常 编译器都不会提示处理这个异常
fun main(args: Array<String>) {
val a = 10
val b = 0
var c: Int =0
try {
c = a/b
} catch (e: Exception) {
println("出现了异常")
}finally {
}
println(c)
}
11.递归
a.递归的使用
fun main(args: Array<String>) {
val result = fact(5)
println(result)
println(fbnq(5))
}
//求n的阶乘 5 5*4的阶乘
fun fact(n:Int):Int{
if(n==1){
return 1
}else{
return n* fact(n-1)
}
}
//斐波那契数列 1 1 2 3 5 8 13 21 34 55
//第n个
fun fbnq(n:Int):Int{
if(n==1||n==2){
return 1
}else{
//第n-1个斐波那契数列 + 第n-2个斐波那契数列
return fbnq(n-1)+ fbnq(n-2)
}
}
b.递归好迭代器的比较
- kotlin函数参数都是不可变的
- 一般情况下:递归能解决的问题 用普通的迭代有也可以解决
- 有一些问题我们用递归解决写起来比较简单,因为递归更加符合思维逻辑
- 迭代:我们需要抽象出数学模型才能解决
- 递归:如果递归的层级比较深的话就会出现栈内存溢出
- 优点 缺点
- 递归: 写起来简单 容易内存溢出
- 迭代 写起来麻烦 不会内存溢出
- 能不能有一种方式既能够写起来简单又能够不会内存溢出呢?尾递归优化(kotlin独有的)
c.尾递归优化
- 尾递归优化需要一个前提:这个递归必须是尾递归
- 尾递归:调用当前递归的方法之后,没有做任何其它操作就是尾递归
- 在尾递归函数前面加上tailrec关键字
- 尾递归优化原理:帮我们把递归转换为迭代 按照递归的方式写代码,按照迭代的方式执行
fun main(args: Array<String>) {
println(add(100000))
}
tailrec fun add(n:Int,result:Int=0):Int{
if(n==1){
return result+1
}else{
return add(n-1,result+n)
}
}