kotlin学习笔记(二)
集合 fun main(args: Array<String>) { val list1 = listOf("asd", "as", "ujkl") //安全操作符 list1.getOrElse(100){"asd"} println(list1.getOrNull(100) ?: "121") //可变的集合 val list2 = mutableListOf("asd", "as", "ujkl") //常见操作 list2.add("asdasd") list2 += "sas" list2.remove("asd") list2 += "uij" list2.removeIf { it.contains("a") } //list跟mutable相互转换 listOf("asd", "as", "ujkl").toMutableList() mutableListOf("asd", "as", "ujkl").toList() //遍历 for (s in list2) { println(s) } list2.forEach { println(it) } list2.forEachIndexed{ index, item -> println("$index, $item") } //set val set1 = setOf("asd", "as", "ujkl") //取出元素 println(set1.elementAt(1)) val set2 = mutableSetOf("asd", "as", "ujkl") //list转set list1.toSet() //直接去重,不需要转set list1.distinct() //kotlin提供现成的数字list var a = intArrayOf(1,2,33) var b = longArrayOf(1L) doubleArrayOf() shortArrayOf() byteArrayOf() floatArrayOf() booleanArrayOf() arrayOf<String>() listOf(1,2,3).toIntArray() //map var map = mapOf("a" to 1, "b" to 2, "c" to 4) //map获取值的方式 println(map["a"]) println(map.getValue("a")) //默认值方式 println(map.getOrElse("asd"){2323}) println(map.getOrDefault("asd", 0)) //map遍历 map.forEach{ println("$it.key,$it.value") } map.forEach{(key : String, value : Int) -> println("$key,$value") } val map2 = mutableMapOf("a" to 1, "b" to 2, "c" to 4) map2 += "o" to 1 map2.put("d", 1) //如果没有就新增 map2.getOrPut("sdasd"){111}}类基本定义class TextByClass{ //属性除非可空,不然必须要给值 //自动生成get/set //可生成get/set时进行操作,必须紧跟属性后面,如果只读可加private var a = "" get() = field.capitalize() private set(value) { field = value.trim() } var b = 1 get() = field.plus(1) set(value) { field = value.div(2) } //不校验空 var c : String ?= "asd" //延迟初始化,用到的时候才会初始化 lateinit var d: String //惰性初始化,首次用的时候才初始化 val config by lazy { lazyText() } private fun lazyText() { println("asd") }}/** * 执行顺序,主构造函数,类定义,init构造函数,次构造函数 */class Payer ( //主构造函数,临时变量用下划线 _id : Int = 1, _name : String, var text : String?){ //次构造函数 constructor(name : String) : this(text = "1", _name = name, _id =1) constructor(name : String, id : Int) : this(text = "1", _name = name, _id = id) { this.name = name.plus(1) } var id = _id var name = _name //初始化块 init { if (id == 1) id = 2 //如果不满足条件,抛出异常 require(id > 0) { "id必须大于0" } }}fun main(args: Array<String>) { var text = TextByClass() println(text.a) //主构造函数创建 var text1 = Payer(1,"2", "w") //次构造函数创建 var text2 = Payer("asd") //默认值方式 var text3 = Payer(_name = "asd", text = "asd")}类的类型知识//类默认都是封闭的,开放继承,必须用open修饰open class ExentText( id :Int? = null){ val id: Int = 1 //可重写方法也用open修饰 open fun load() = "asd"}class ChText : ExentText(1) { override fun load() = "asd" fun abc() = "asd"}//单例对象,使用object声明object ApplicationConfig { fun doSomething() = "asd"}//伴生对象companion,不管实例多少次,只有一个伴生对象(单例)open class ConfigMap { companion object{ private const val PATH ="d:\\1.txt" fun load() = java.io.File(PATH).readText() }}//嵌套类,如果一个类针对一个类有用,可以嵌入到该类中class Text2() { class Text3() { fun show() = "asd" }}//数据类data修饰data class DataText( var a : String, var b : String) { var ab = a+b //运算符重载 operator fun plus(other:DataText) = DataText(a + other.a, b+other.b)}//解构函数class Text5(val a:Int, val b: Int) { operator fun component1() = a operator fun component2() = b}//枚举类,可定义方法enum class EnumText(private val coordinate : ExentText){ WEST(ExentText(1)), EAST(ExentText(2)); fun updateData(playData : ExentText) = ExentText(playData.id.plus( coordinate.id))}fun main(args: Array<String>) { val a = ChText() //is关键字,检查是否是该类型 println(a is ChText) println(a is ExentText) //as进行类型转换 if (a is ChText) { println((a as ChText).abc()) } //Any是所有类的超类 println(a is Any) println(ApplicationConfig.doSomething()) //只用一次的类,可以用object声明;p val p = object : ExentText() { override fun load(): kotlin.String { return "asd" } } println(p.load()) ConfigMap.load() Text2.Text3().show() val dataText = DataText("a", "b") //copy函数。复制一个对象 val copy = dataText.copy(a = "c", b = "b") var (x, y) = Text5(1,2) println("$x, $y") //数据类型直接支持 var (x1, y1) = DataText("1","2") println(EnumText.EAST) println(EnumText.EAST.updateData(ExentText(1)))}类补充enum class Dir{ APPLE, CAR, BUTTON;}class DefaultClass(var dir : Dir){ fun getDir() : String { return when(dir) { Dir.APPLE -> "aaa" Dir.CAR -> "ccc" else -> "ddd" } }}//密封类sealed class License { object apple : License() object car : License() class button(var id : Int) : License()}//比enum多返回数据class DefaultClass2(var dir : License){ fun getDir() : String { return when(dir) { is License.apple -> "aaa" is License.button -> "ccc ${(this.dir as License.button).id}" else -> "ddd" } }}fun main(args: Array<String>) { println(DefaultClass(Dir.CAR).getDir())}
spring boot定时任务
由于这段时间事情有点多,所以没怎么更新,所以今天就说个简单的——定时任务。 在spring boot中实现定时任务很简单。直接上代码。 import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.Scheduled;import java.text.SimpleDateFormat;import java.util.Date;@Configuration@EnableSchedulingpublic class SchedulingConfig { @Scheduled(cron = "0/5 * * * * ?") // 每5秒执行一次 public void scheduler() { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(formatter.format(new Date())+"----->执行任务"); }}接下来,我们在Application中设置启用定时任务功能import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableScheduling;@EnableScheduling@SpringBootApplicationpublic class BlogApplication { public static void main(String[] args) { SpringApplication.run(BlogApplication.class, args); }}执行结果 关于cron表达式的介绍,来源于其他博客cronExpression定义时间规则,Cron表达式由6或7个空格分隔的时间字段组成:秒 分钟 小时 日期 月份 星期 年(可选);字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 , - * /
星期 1-7 , - * ? / L C #
年 1970-2099 , - * /解析:
0/5 * * * * ? : 每5秒执行一次“*”字符被用来指定所有的值。如:"*"在分钟的字段域里表示“每分钟”。
“?”字符只在日期域和星期域中使用。它被用来指定“非明确的值”。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。看下面的例子你就会明白。
月份中的日期和星期中的日期这两个元素时互斥的一起应该通过设置一个问号来表明不想设置那个字段。“-”字符被用来指定一个范围。如:“10-12”在小时域意味着“10点、11点、12点”。“,”字符被用来指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”。“/”字符用于指定增量。如:“0/15”在秒域意思是每分钟的0,15,30和45秒。“5/15”在分钟域表示每小时的5,20,35和50。 符号“*”在“/”前面(如:*/10)等价于0在“/”前面(如:0/10)。记住一条本质:表达式的每个数值域都是一个有最大值和最小值的集合,如: 秒域和分钟域的集合是0-59,日期域是1-31,月份域是1-12。字符“/”可以帮助你在每个字符域中取相应的数值。如:“7/6”在月份域的时候只 有当7月的时候才会触发,并不是表示每个6月。L是‘last’的省略写法可以表示day-of-month和day-of-week域,但在两个字段中的意思不同,例如day-of- month域中表示一个月的最后一天。如果在day-of-week域表示‘7’或者‘SAT’,如果在day-of-week域中前面加上数字,它表示 一个月的最后几天,例如‘6L’就表示一个月的最后一个星期五。字符“W”只允许日期域出现。这个字符用于指定日期的最近工作日。例如:如果你在日期域中写 “15W”,表示:这个月15号最近的工作日。所以,如果15号是周六,则任务会在14号触发。如果15好是周日,则任务会在周一也就是16号触发。如果 是在日期域填写“1W”即使1号是周六,那么任务也只会在下周一,也就是3号触发,“W”字符指定的最近工作日是不能够跨月份的。字符“W”只能配合一个 单独的数值使用,不能够是一个数字段,如:1-15W是错误的。“L”和“W”可以在日期域中联合使用,LW表示这个月最后一周的工作日。字符“#”只允许在星期域中出现。这个字符用于指定本月的某某天。例如:“6#3”表示本月第三周的星期五(6表示星期五,3表示第三周)。“2#1”表示本月第一周的星期一。“4#5”表示第五周的星期三。字符“C”允许在日期域和星期域出现。这个字符依靠一个指定的“日历”。也就是说这个表达式的值依赖于相关的“日历”的计算结果,如果没有“日历” 关联,则等价于所有包含的“日历”。如:日期域是“5C”表示关联“日历”中第一天,或者这个月开始的第一天的后5天。星期域是“1C”表示关联“日历” 中第一天,或者星期的第一天的后1天,也就是周日的后一天(周一)。例子如下:0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发