Kotlin学习笔记——(四)List、Set、Map、数组和类

注:编码工具为IntelliJ

目录

List

创建

元素获取

可变和不可变List的区别

MutableList的mutator函数和removeIf

遍历

方式一:

方式二:

解构

Set

元素获取

MutableSet的mutator函数和removeIf

List转Set去重

Map

创建

元素获取

遍历

方式一

方式二:

方式三:

方式四:

可变Map的mutator函数和增删改操作

数组

元素获取

与List、Set之间的转换

对象数组

极简类定义

有成员变量的类的定义简单示例

类成员的get、set属性和field

构造函数

主构造函数

次构造函数

构造函数默认参数

init初始化块

构造函数初始化顺序

延迟初始化:lateinit

by lazy:懒加载

一些初始化错误:

一:编译不过

二:

三:


List

创建

        List分为可变和不可变两种,之间可以相互转换。

fun main() {
    val intList = listOf(1, 2, 3) // 创建可变List
    val intMutableList = mutableListOf(1, 2, 3)// 创建不可变List
    println(intList)
    println(intMutableList)
    println(intList.toMutableList())// 不可变List转换为可变List
    println(intMutableList.toList())// 可变List转换为不可变List
}

输出:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]

元素获取

        可变和不可变List获取元素方式相同:get、[]、getOrElse、getOrNull。

        get和[]本质相同,下标越界会抛异常。

        getOrElse,如果下标没越界,返回对应下标的元素,否则,返回指定值。

        getOrNull,如果下标没越界,返回对应下边的元素,否则,返回null。

fun main() {
    val list = mutableListOf(111, 2, 333, 4)
    println(list.get(0))
//    println(list.get(4))// java.lang.IndexOutOfBoundsException
    println(list[3])// [] 实际和get本质相同
//    println(list[30])// java.lang.IndexOutOfBoundsException

    println(list.getOrElse(3) { 9 })
    println(list.getOrElse(33) { 9 })
    println(list.getOrNull(2))
    println(list.getOrNull(100))
}

输出:

111
4
4
9
333
null

可变和不可变List的区别

       可以对可变List进行元素的增删改操作。

fun main() {
    val list = mutableListOf("I", "Miss", "You")
    println(list)
    list.add("Hope")
    println(list)
    list.set(1, "Love")
    println(list)
    list.remove("Hope")
    println(list)
}

输出:

[I, Miss, You]
[I, Miss, You, Hope]
[I, Love, You, Hope]
[I, Love, You]

MutableList的mutator函数和removeIf

        mutator函数:+= 添加元素、-= 移除元素

        removeIf函数:删除满足条件的元素

fun main() {
    val list = mutableListOf("A", "D", "Min", "i", "S")
    list += "T" // += 等于 add
    println(list)
    list -= "Min"// -= 等于 remove
    println(list)
    list.removeIf { it >= "i" }
    println(list)
}

输出:

[A, D, Min, i, S, T]
[A, D, i, S, T]
[A, D, S, T]

遍历

方式一:

fun main() {
    val list = listOf(1, 3, 4)
    for(i in list)
    {
        print("$i ")
    }
}

输出:

1 3 4 

方式二:

fun main() {
    val list = listOf(1, 3, 4)
    list.forEach {
        print("$it ")
    }
}

输出:

1 3 4 

方式三:

fun main() {
    val list = listOf(1, 3, 4)
    list.forEachIndexed { index, i ->
        print("$index-$i ")
    }
}

输出:

0-1 1-3 2-4 

解构

fun main(){
    val list = mutableListOf("A", "B", "C", "Z")
    println(list)
    var (a, b, c, d) = list
    println("a:$a, b:$b, c:$c, d:$d")
    val (_, f, g, h) = list// _符号可以屏蔽不想解构的元素
    println("f:$f, g:$g, h:$h)
}

输出:

[A, B, C, Z]
a:A, b:B, c:C, d:Z
f:B, g:C, h:Z

Set

        特点:元素不可重复,可用于去重。

        Set分为可变和不可变两种,之间可以相互转换。

        可以和List之间相互转换。

fun main() {
    val intSet = setOf(1, 2, 3, 4, 4)// 创建不可变Set
    println(intSet)// 只有一个4
    val intMutableSet = mutableSetOf(1, 2, 1, 3, 4)// 创建可变Set
    println(intMutableSet)// 只有一个1
    println("-----------Set之间转换------------")
    println(intSet.toMutableSet())// 不可变Set转换为可变Set
    println(intMutableSet.toSet())// 可变Set转换为不可变Set
    println("-----------Set To List------------")
    println(intSet.toList())// 不可变Set转换为不可变List
    println(intSet.toMutableList())// 不可变Set转换为可变List
    println(intMutableSet.toList())// 可变Set转换为不可变List
    println(intMutableSet.toMutableList())// 可变Set转换为可变List
    println("-----------List To Set------------")
    val charList = listOf('a', 'b', 'c', 'd')
    val charMutableList = mutableListOf('d', 'c', 'b', 'a')
    println(charList.toSet())// 不可变List转换为不可变Set
    println(charList.toMutableSet())// 不可变List转换为可变Set
    println(charMutableList.toSet())// 可变List转换为不可变Set
    println(charMutableList.toMutableSet())// 可变List转换为可变Set
}

输出:

[1, 2, 3, 4]
[1, 2, 3, 4]
-----------Set之间转换------------
[1, 2, 3, 4]
[1, 2, 3, 4]
-----------Set To List------------
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
-----------List To Set------------
[a, b, c, d]
[a, b, c, d]
[d, c, b, a]
[d, c, b, a]

元素获取

        可变和不可变Set获取元素方式相同:elementAt, elementAtOrElse、elementAtOrNull。

        elementAt下标越界会抛异常。

        elementAtOrElse,如果下标没越界,返回对应下标的元素,否则,返回指定值。

        elementAtOrNull,如果下标没越界,返回对应下边的元素,否则,返回null。

fun main() {
    val set = setOf(1, 3, 2, 5)
    // set.elementAt(5) // java.lang.IndexOutOfBoundsException
    println(set.elementAt(0))
    println(set.elementAtOrElse(3) { it })
    println(set.elementAtOrElse(5) { it })
    println(set.elementAtOrNull(1))
    println(set.elementAtOrNull(100))
}

输出:

1
5
5
3
null

MutableSet的mutator函数和removeIf

        mutator函数:+= 添加元素、-= 移除元素

        removeIf函数:删除满足条件的元素

fun main() {
    val set = mutableSetOf("A", "T", "Z")
    println(set)
    set += "O"
    set += "ABC"
    println(set)
    set -= "\""
    set -= "ABC"
    println(set)
    set.removeIf{
        it == "O"
    }
    println(set)
}

输出:

[A, T, Z]
[A, T, Z, O, ABC]
[A, T, Z, O]
[A, T, Z]

List转Set去重

fun main() {
    val list = listOf(1, 3, 5, 3, 3, 2, 5)
    println(list)
    println(list.toSet())
    println(list.toSet().toList())
}

输出:

[1, 3, 5, 3, 3, 2, 5]
[1, 3, 5, 2]
[1, 3, 5, 2]

Map

创建

        Map分为可变和不可变两种,之间可以相互转换。

fun main() {
    val map = mapOf(1 to 2, 3 to 4, 5 to 6)
    val mutableMap = mutableMapOf(Pair('a', 1), Pair('b', 2), 'c' to 3)
    println(map.toMutableMap())// 不可变Map转换为可变Map
    println(mutableMap.toMap())// 可变Map转换为不可变Map
}

输出:

{1=2, 3=4, 5=6}
{a=1, b=2, c=3}

元素获取

        可变和不可变Map获取元素方式相同:[]、get、getValue、getOrDefault、getOrElse。

        []和get本质相同,key不存在返回null。

        getValue,如果key存在,返回对应value,否则,抛出异常。

        getOrDefault,如果key存在,返回对应value,否则,返回default值。

        getOrElse,如果下标没越界,返回对应value,否则,返回指定值。

fun main() {
    val map = mutableMapOf(1 to 'a', 2 to 'c', 3 to 'e')
    println(map[1])
    println(map[4])// key不存在返回null
    println(map.get(2))
    println(map.get(100))// key不存在返回null
    println(map.getValue(3))
    // println(map.getValue(1000))// java.util.NoSuchElementException
    println(map.getOrDefault(1, 'A'))
    println(map.getOrDefault(15, 'A'))
    println(map.getOrElse(1) { 'E' })
    println(map.getOrElse(99) { 'V' })
}

输出:

a
null
c
null
e
a
A
a
V

遍历

方式一

fun main() {
    val map = mapOf('A' to 'Z', 'B' to 'Y')
    for(i in map){
        println("key = ${i.key}, value = ${i.value}")
    }
}

输出:

key = A, value = Z
key = B, value = Y

方式二:

fun main() {
    val map = mapOf('A' to 'Z', 'B' to 'Y')
    for((k, v) in map){
        println("$k:$v")
    }
}

输出:

A:Z
B:Y

方式三:

fun main() {
    val map = mapOf('A' to 'Z', 'B' to 'Y')
    map.forEach{
        println("${it.key} to ${it.value}")
    }
}

输出:

A to Z
B to Y

方式四:

fun main() {
    val map = mapOf('A' to 'Z', 'B' to 'Y')
    map.forEach{(k, v) -> println("k = $k, v = $v")}
}

输出:

k = A, v = Z
k = B, v = Y

可变Map的mutator函数和增删改操作

fun main() {
    val map = mutableMapOf(3 to 5, 7 to 1)
    println(map)
    map += 3 to 9
    println(map)
    map += 10 to 2
    println(map)
    map += 4 to 100
    println(map)
    map -= 1
    println(map)
    map -= 7
    println(map)
    map[33] = 333
    println(map)
    map.put(3, 13)
    println(map)
    println(map.getOrPut(3){10000})
    println(map.getOrPut(100){10000})
}

输出:

{3=5, 7=1}
{3=9, 7=1}
{3=9, 7=1, 10=2}
{3=9, 7=1, 10=2, 4=100}
{3=9, 7=1, 10=2, 4=100}
{3=9, 10=2, 4=100}
{3=9, 10=2, 4=100, 33=333}
{3=13, 10=2, 4=100, 33=333}
13
10000

数组

创建

fun main() {
    val arrayOf = arrayOf('a', 'A', 'C')
    println(arrayOf.contentDeepToString())
    val intArr = intArrayOf(1, 2, 3)
    println(intArr.contentToString())
    /**
     * 类似的还有
     * shortArrayOf()
     * byteArrayOf()
     * charArrayOf()
     * longArrayOf()
     * booleanArrayOf()
     * floatArrayOf()
     * doubleArrayOf()
     */
}

输出:

[a, A, C]
[1, 2, 3]

元素获取

        []、get、elementAt、elementAtOrElse、elementAtOrNull。

        []、get、elementAt本质相同,下标越界会抛异常。

        elementAtOrElse,如果下标没越界,返回对应下标的元素,否则,返回指定值。

        elementAtOrNull,如果下标没越界,返回对应下边的元素,否则,返回null。

fun main() {
    val arr = arrayOf(1, 2, 3)
    println(arr.contentToString())
    println(arr[2])
    // println(arr[3])// java.lang.ArrayIndexOutOfBoundsException
    println(arr.get(0))
    arr.set(2,20)
    println(arr.contentToString())
    println((arr + 4).contentToString())
    // println((arr - 3).contentToString()) // 没有-符号重载
    println(arr.elementAt(0))
    println(arr.elementAtOrElse(5) { it })
    println(arr.elementAtOrNull(5))
}

输出:

[1, 2, 3]
3
1
[1, 2, 20]
[1, 2, 20, 4]
1
5
null

与List、Set之间的转换

fun main() {
    val intArr = intArrayOf(1, 2, 3, 4)
    println(intArr.toSet())// Array转换为Set
    println(intArr.toList())// Array转换为List
    val set = setOf("I", "Love", "MySelf")
    println(set.toTypedArray().contentToString())// Set转换为Array
    val list = listOf("I", "Trust", "MySelf")
    println(list.toTypedArray().contentToString())// list转换为Array
}

输出:

[1, 2, 3, 4]
[1, 2, 3, 4]
[I, Love, MySelf]
[I, Trust, MySelf]

对象数组

fun main() {
    val peopleArray = arrayOf(Person("ZhangSan"), Person("LiSi"))
    for (person in peopleArray)
    {
        println(person.name)
    }
}

输出:

ZhangSan
LiSi

极简类定义

        只有类名,如下所示:

class MinimalistClass

有成员变量的类的定义简单示例

class Demo{
    var name: String = ""

    val grade: String = "3"
}

反编译后的Java代码:

public final class Demo {
   @NotNull
   private String name = "";
   @NotNull
   private final String grade = "3";

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }

   @NotNull
   public final String getGrade() {
      return this.grade;
   }
}

        如上所示,Kotlin的类成员变量反编译成Java代码后会变为private的,其中var修饰的变量会提供getter、setter,而val修饰的变量则只会提供getter。

类成员的get、set属性和field

        Kotlin的类成员默认都有一个field变量,var修饰的变量默认会提供set()和get()方法,val修饰的变量默认会提供get()方法。

        set()方法默认会将入参赋值给field,get()方法默认会返回field。

        可以自定义var修饰的变量的set()和get()方法,val修饰的变量的get()方法。

class Field{
    var name: String = "Knuth"// var 修饰的变量既有set() 又有get()
        set(value){
            field = value
        }
        get() = "[$field]"
    val hobby = "travel" //val 修饰的变量只有get()
        get() = "hobby:$field"
    val age : Int // = 1 不能赋值,因为在get()方法中给定了值,使其没有后端field
        get() {
            println("before get age")
            return 99
        }
}

fun main() {
    val field = Field()
    println("name = ${field.name}, hobby = ${field.hobby}, age = ${field.age}")
}

输出:

before get age
name = [Knuth], hobby = hobby:travel, age = 99

构造函数

主构造函数

        在类型后面加一对圆括号,如果没有参数,圆括号可以省略,否则,在圆括号里进行参数声明。

        有参数:

        没有var/val修饰,需要在类内部定义变量接收主构造函数中传入的参数;

        有var/val修饰,主构造函数的参数直接作为类的成员变量使用。

没有var/val修饰示例:

class MainCon(name: String, age: Int){
    var name = name
    var age = age
}

反编译后的Java代码:

public final class MainCon {
   @NotNull
   private String name;
   private int age;

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public final void setAge(int var1) {
      this.age = var1;
   }

   public MainCon(@NotNull String name, int age) {
      Intrinsics.checkNotNullParameter(name, "name");
      super();
      this.name = name;
      this.age = age;
   }
}

有var/val修饰示例:

class MainCon2(var name: String, val age: Int)

反编译后的Java代码:

public final class MainCon2 {
   @NotNull
   private String name;
   private final int age;

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public MainCon2(@NotNull String name, int age) {
      Intrinsics.checkNotNullParameter(name, "name");
      super();
      this.name = name;
      this.age = age;
   }
}

次构造函数

        必须调用主构造函数。

        有参数时不能用var/val修饰。

        有参数且主构造函数没有参数时,只能定义成员变量接收。

class SubCon(){
    var name: String = ""
    constructor(name: String) : this(){
        this.name = name
    }
}

        有参数且主构造函数有参数且用var/val修饰时,可以将参数传给主构造函数然后直接作为属性使用。

class SubCon2(var name: String, var age:Int){
    constructor(name: String): this(name, 99)
}

构造函数默认参数

class Content(var name: String, var age: Int = 99){
    constructor(name: String = "Default"):this(name, 88)
}

fun main() {
    val content = Content("happy")
    println("name = ${content.name}, age = ${content.age}")
    val content2 = Content("Seo")
    println("name = ${content2.name}, age = ${content2.age}")
    val content3 = Content("author", 100)
    println("name = ${content3.name}, age = ${content3.age}")
}

输出:

name = happy, age = 88
name = Seo, age = 88
name = author, age = 100

init初始化块

        主构造函数调用时被调用,可用于初始化定义在类内部的成员变量。

class InitTest(name: String, age: Int){
    var name: String
    var age: Int
    init{
        this.name = name
        this.age = age
    }
    fun show(){
        println("name:$name, age:$age")
    }
}

fun main() {
    InitTest("C.C", 999999).show()
}

输出:

name:C.C, age:999999

构造函数初始化顺序

// 第二步
class Student(var name: String, age: Int){
    // gender赋值、init块和bornPlace赋值按照代码先后顺序执行
    // 第三步
    var gender = "M"
    var age: Int
    init{
        // 第四步
        this.age = age
    }
    // 第五步
    val bornPlace = "BeiJing"
    
    // 第一步
    constructor(name: String):this(name,18)
}

fun main() {
    Student("小明")
}

延迟初始化:lateinit

class Animal{
    lateinit var name: String

    fun show(){
        if(::name.isInitialized)
        {
            println("name is $name")
        }else{
            println("name has not been initialized")
        }
    }

    fun init(){
        name = "AFu"
        show()
    }
}

fun main() {
    val animal = Animal()
    animal.show()
    animal.init()
}

输出:

name has not been initialized
name is AFu

by lazy:懒加载

        在用到的时候才加载

class LazyDemo{
    // 在类实例定义时会执行赋值操作,所以会调用init,所以info会被立即赋值
    var info = init()

    // 在类实例定义时不会执行赋值操作,在info第一次被用到的时候才会被赋值
    val into2 by lazy {
        println("do once")
        "this is a lazy load value"
    }

    fun init(): String{
        println("do something...")
        return "HH"
    }
}

fun main() {
    val ld = LazyDemo()// 会执行init方法给info赋值

    println("---------------------------")

    println("info is ${ld.info}")

    println("info2 is ${ld.into2}")
    println("info2 is ${ld.into2}")
}

输出:

do something...
---------------------------
info is HH
do once
info2 is this is a lazy load value
info2 is this is a lazy load value

一些初始化错误:

        理解了构造函数初始化顺序就能理解错误原因。

一:编译不过

class InitError1{
    init{
        number = number.times(9)
    }
    var number = 9
}

二:

class InitError2{
    var info : String
    init{
        showInfo()
        info = "Init"
    }

    fun showInfo(){
        println("${info[0]}")
    }
}

fun main() {
    InitError2()// java.lang.NullPointerException
}

输出:

Exception in thread "main" java.lang.NullPointerException
	at step_four.InitError2.showInfo(InitError2.kt:11)
	at step_four.InitError2.<init>(InitError2.kt:6)
	at step_four.InitError2Kt.main(InitError2.kt:16)
	at step_four.InitError2Kt.main(InitError2.kt)

三:

class InitError3(i: String){
    val c = get()
    val info = i
    fun get() = info
}

fun main(){
    println(InitError3("MoonLight").c.length)// java.lang.NullPointerException
}

输出:

Exception in thread "main" java.lang.NullPointerException
    at step.four.InitError3Kt.main(InitError3.kt:10)
    at step.four.InitError3Kt.main(InitError3.kt)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值