Kotlin-数组与集合-Array

Kotlin 为数组添加了一个Array类,使用Array<T>来表示。

声明和创建 Array

  1. arrayOf(vararg elements: T): Array<T>
    声明时传入所有元素
    Kotlin 此时可以推断出数组元素的类型,所以就不需要在 arrayOf() 函数上使用泛型来指定数组元素的类型。
  2. arrayOfNulls(size: Int): Array<T?>
    显式指定数组的长度,数组全部初始化为 null
    Kotlin 此时无法推断出数组元素类型,所以需要在 arrayOfNulls() 函数上使用泛型来指定数组元素的类型。
  3. emptyArray(): Array<T>
    创建一个长度为0的空数组
    Kotlin 此时无法推断出数组元素类型,所以需要在 emptyArray() 函数上使用泛型来指定数组元素的类型。
  4. Array<T> constructor(size: Int, init: (Int) -> T)
    显式指定数组的长度,并可通过 Lambda 表达式来计算个数组元素的值
// 创建包含指定元素的数组
val array1 = arrayOf("Java", "Kotlin", "Go") //["Java", "Kotlin", "Go"]
val intArray1 = arrayOf(1, 2, 400, -90) //[1, 2, 400, -90]

// 创建指定长度,元素为 null 的数组
val array2 = arrayOfNulls<String>(5) //[null, null, null, null, null]
val intArray2 = arrayOfNulls<Int>(10) //[null, null, null, null, null, null, null, null, null, null]

// 创建长度为0的空数组
val array3 = emptyArray<String>() //[]
val intArray3 = emptyArray<Int>() //[]

// 创建指定长度,并使用 Lambda 表达式来初始化元素的数组
val array4 = Array(6) {"Language $it"} //["Language 0", "Language 1", "Language 2", "Language 3", "Language 4", "Language 5"]
val intArray4 = Array(5) {it * 2 + 97} //[97, 99, 101, 103, 105]

当元素为基本类型的值时,Koltin 还为提供了以下8种实例:

实例 初始化
ByteArray byteArrayOf(vararg elements: Byte): ByteArray
ByteArray constructor(size: Int, init: (Int) -> Byte)
ShortArray shortArrayOf(vararg elements: Short): ShortArray
ShortArray constructor(size: Int, init: (Int) -> Short)
IntArray intArrayOf(vararg elements: Int): IntArray
IntArray constructor(size: Int, init: (Int) -> Int)
LongArray longArrayOf(vararg elements: Long): LongArray
LongArray constructor(size: Int, init: (Int) -> Long)
CharArray charArrayOf(vararg elements: Char): CharArray
CharArray constructor(size: Int, init: (Int) -> Char)
FloatArray floatArrayOf(vararg elements: Float): FloatArray
FloatArray constructor(size: Int, init: (Int) -> Float)
DoubleArray doubleArrayOf(vararg elements: Double): DoubleArray
DoubleArray constructor(size: Int, init: (Int) -> Double)
BooleanArray booleanArrayOf(vararg elements: Boolean): BooleanArray
BooleanArray constructor(size: Int, init: (Int) -> Boolean)

使用 Array 中的方法

  1. all(predicate: (T) -> Boolean): Boolean
val array = arrayOf("Java", "Kotlin", "Go")
// 如果所有的元素都满足给定的条件,则返回 true
println(array.all { it.length > 4 }) //false
  1. any(predicate: (T) -> Boolean): Boolean
val array = arrayOf("Java", "Kotlin", "Go")
// 如果至少有一个元素满足给定的条件,则返回 true
println(array.any { it.length > 4 }) //true
  1. 转换成 List
    asList(): List<T>
val array = arrayOf("Java", "Kotlin", "Go")
// 将该数组转换成 List 集合
println(array.asList()) //[Java, Kotlin, Go]
  1. 转换成 Map
    associate(transform: (T) -> Pair<K, V>): Map<K, V>
    associateTo(destination: M, transform: (T) -> Pair<K, V>): M
    associateBy(keySelector: (T) -> K): Map<K, T>
    associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map<K, V>
    associateByTo(destination: M, keySelector: (T) -> K): M
    associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M
val array = arrayOf("Java", "Kotlin", "Go")
val map = mutableMapOf(10 to "TypeScript", 5 to "Swift")
// 使用 Lambda 表达式根据数组元素计算,返回 Map<K, V>
println(array.associate { it.length to "$it length" }) //{4=Java length, 6=Kotlin length, 2=Go length}
// 使用 Lambda 表达式根据数组元素计算,并添加到可变 map 集合中,返回修改后的 map
println(array.associateTo(map, { it.length to "$it length" })) //{10=TypeScript, 5=Swift, 4=Java length, 6=Kotlin length, 2=Go length}
// 使用 Lambda 表达式根据数组元素计算,返回 Map<K, V>,其中 V 是数组元素
println(array.associateBy { it.length }) //{4=Java, 6=Kotlin, 2=Go}
// 使用 Lambda 表达式根据数组元素计算,返回 Map<K, V>
println(array.associateBy({ it.length }, { "$it length" })) //{4=Java length, 6=Kotlin length, 2=Go length}
// 使用 Lambda 表达式根据数组元素计算,并添加到可变 map 集合中,返回修改后的 map
println(array.associateByTo(map, { it.length })) //{10=TypeScript, 5=Swift, 4=Java, 6=Kotlin, 2=Go}
// 使用 Lambda 表达式根据数组元素计算,并添加到可变 map 集合中,返回修改后的 map
println(array.associateByTo(map, { it.length }, { "$it length" })) //{10=TypeScript, 5=Swift, 4=Java length, 6=Kotlin length, 2=Go length}
  1. 计算数值型数组的平均值
    average(): Double
val intArray = intArrayOf(2, 67, 6, -1)
// 计算数值型数组的平均值
println(intArray.average()) //18.5
  1. 二分查找(数组元素必须按照升序排序)
    binarySearch(element: Int, fromIndex: Int = 0, toIndex: Int = size): Int
val intAscArray = intArrayOf(-1, 2, 6, 67)
val intArray = intArrayOf(2, 67, 6, -1)
// 用二分法查找元素在数组中出现的位置,要求数组中的元素按升序排列,否则无法得到正确的结果
println(intAscArray.binarySearch(6)) //2,由于数组元素是升序,故结果正确
println(intArray.binarySearch(6)) // -2,由于数组元素无序,故结果错误
  1. 包含
    contains(element: T): Boolean
val array = arrayOf("Java", "Kotlin", "Go")
// 判断该数组是否包含某个元素,可使用 in !in 运算符执行
println(array.contains("Java")) //true
println("Swift" in array) //false
  1. 相等比较
    contentEquals(other: Array<out T>?): Boolean
val array = arrayOf("Java", "Kotlin", "Go")
// 比较两个数组是否相等
val otherArray = arrayOf("Java", "Kotlin", "Go")
println(array.contentEquals(otherArray)) //true
  1. 转换为字符串
    contentToString(): String
val array = arrayOf("Java", "Kotlin", "Go")
// 把数组转换成字符串
println(array.contentToString()) // "[Java, Kotlin, Go]"
  1. 复制数组
    copyOf(): Array<T>
    copyOf(newSize: Int): Array<T?>
    copyOfRange(fromIndex: Int, toIndex: Int): Array<T>
val array = arrayOf("Java", "Kotlin", "Go")
// 复制一个新数组,若指定 size:<= 原size,取前 size 个;> 原size,不足的后面补0(数值类型),false(布尔类型),null(引用类型)
println(array.copyOf().asList()) //[Java, Kotlin, Go]
println(array.copyOf(2).asList()) //[Java, Kotlin]
println(array.copyOf(5).asList()) //[Java, Kotlin, Go, null, null]
// 复制一个新数组,指定区间范围,不可超过原数组的 size
println(array.copyOfRange(1, 2).asList()) //[Kotlin]
  1. 获取元素个数
    count(predicate: (T) -> Boolean): Int
    count(): Int
val array = arrayOf("Java", "Kotlin", "Go")
// 返回该数组给定 Lambda 条件的元素个数,若不指定参数,则返回数组中的元素个数,与 size 相同
println(array.count { it.length > 4 }) //1
println(array.count()) //3
  1. 数组去重
    distinct(): List<T>
val distinctArray = arrayOf("one", "two", "five", "one")
// 该方法用于去掉数组中的重复元素
println(distinctArray.distinct()) //[one, two, five]
  1. 删除数组首位元素
    drop(n: Int): List<T>
    dropLast(n: Int): List<T>
    dropWhile(predicate: (T) -> Boolean): List<T>
    dropLastWhile(predicate: (T) -> Boolean): List<T>
val array = arrayOf("Java", "Kotlin", "Go")
// 去掉数组前面或后面 n 个元素,n >= size 时,返回空集合
println(array.drop(1)) //[Kotlin, Go]
println(array.drop(4)) //[]
println(array.dropLast(1)) //[Java, Kotlin]
println(array.dropLast(4)) //[]
// 去掉数组前面或后面的某些元素,直到不满足条件为止
println(array.dropWhile { it.length >= 4 }) //[Go]
println(array.dropLastWhile { it.length < 4 }) //[Java, Kotlin]
  1. 覆盖元素
    fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit
val array = arrayOf("Java", "Kotlin", "Go")
// 将数组从 fromIndex 到 toIndex 索引的元素赋值为 element
array.fill("Swift", 0, array.size)
println(array.asList()) //[Swift, Swift, Swift]
  1. 过滤集合
    filter(predicate: (T) -> Boolean): List<T>
    filterTo(destination: C, predicate: (T) -> Boolean): C
    filterIndexed(predicate: (index: Int, T) -> Boolean): List<T>
    filterIndexedTo(destination: C, predicate: (index: Int, T) -> Boolean): C
    filterIsInstance(): List<@kotlin.internal.NoInfer R>
    filterIsInstance(klass: Class<R>): List<R>
    filterIsInstanceTo(destination: C): C
    filterIsInstanceTo(destination: C, klass: Class<R>): C
    filterNot(predicate: (T) -> Boolean): List<T>
    filterNotTo(destination: C, predicate: (T) -> Boolean): C
    filterNotNull(): List<T>
    filterNotNullTo(destination: C): C
val array = arrayOf("Java", "Kotlin", "Go")
// filterXxx,一系列过滤数组元素的方法
// 根据 Lambda 表达式中的条件进行过滤
println(array.filter { it.length > 4 }) //[Kotlin]
// 根据 Lambda 表达式中的条件进行过滤,并添加到 C 中
val otherList = mutableListOf("C++")
println(array.filterTo(otherList, { it.length > 4 })) //[C++, Kotlin]
// 根据 Lambda 表达式中的条件进行过滤,index:索引 s:元素值
println(array.filterIndexed { index, s -> index >=1 && s.length > 1 }) //[Kotlin, Go]
// 根据 Lambda 表达式中的条件进行过滤,index:索引 s:元素值,并添加到另个可变集合 c 中,最终返回 c
val filterOtherArray = mutableListOf("TypeScript", "JavaScript")
println(array.filterIndexedTo(filterOtherArray, { index, s -> index >=1 && s.length > 1 })) //[TypeScript, JavaScript, Kotlin, Go]
// filterIsInstance 返回数组中是 R 的实例的元素,适用于一个抽象类集合中有多种子元素的情况
val animals = arrayOf(
    Dog("Dog 1"),
    Cat("Cat 1"),
    Bird("Bird 1"),
    Dog("Dog 2")
)
println(animals.filterIsInstance<Dog>()) //[Dog 1, Dog 2]
println(animals.filterIsInstance(Dog::class.java)) //[Dog 1, Dog 2]
// filterIsInstanceTo 返回数组中是 R 的实例的元素,并添加到 C 中
val dogs = mutableListOf(
    Dog("Dog a"),
    Dog("Dog b")
)
println(animals.filterIsInstanceTo(dogs)) //[Dog a, Dog b, Dog 1, Dog 2]
println(animals.filterIsInstanceTo(dogs, Dog::class.java)) //[Dog a, Dog b, Dog 1, Dog 2, Dog 1, Dog 2]
// 返回一个与给定条件不匹配的 List 集合,与 filter 方法取反
println(animals.filterNot { it.name == "Dog 1" }) //[Cat 1, Bird 1, Dog 2]
// 返回一个与给定条件不匹配的 List 集合,并添加到 C 中,与 filterTo 方法取反
val otherAnimals = mutableListOf(
    Dog("Dog a"),
    Cat("Cat a"),
    Bird("Bird a"),
    Dog("Dog b")
)
println(animals.filterNotTo(otherAnimals, { it.name == "Dog 1" })) //[Dog a, Cat a, Bird a, Dog b, Cat 1, Bird 1, Dog 2]
// 过滤掉 null,返回一个没有 null 的 List
val nullableArray = arrayOf("aaa", "bbb", null, "ccc")
println(nullableArray.filterNotNull()) //[aaa, bbb, ccc]
// 过滤掉 null,并添加到 C 中,返回 C
val otherNullableList = mutableListOf("AAA", null, "BBB")
println(nullableArray.filterNotNullTo(otherNullableList)) //[AAA, null, BBB, aaa, bbb, ccc]

abstract class Animal(var name: String)

class Dog(name: String) : Animal(name) {
    override fun toString(): String = name
}

class Cat(name: String) : Animal(name) {
    override fun toString(): String = name
}

class Bird(name: String) : Animal(name) {
    override fun toString(): String = name
}
  1. 查找元素
    find(predicate: (T) -> Boolean): T?
    findLast(predicate: (T) -> Boolean): T?
val array = arrayOf("Java", "Kotlin", "Go")
// findXxx 一系列用于查找元素的方法
println(array.find { it.length > 2 }) //Java
println(array.findLast { it.length > 2 }) //Kotlin
  1. 返回第一个/最后一个元素
    first(): T
    first(predicate: (T) -> Boolean): T
    firstOrNull(): T?
    firstOrNull(predicate: (T) -> Boolean): T?
    last(): T
    last(predicate: (T) -> Boolean): T
    lastOrNull(): T?
    lastOrNull(predicate: (T) -> Boolean): T?
val array = arrayOf("Java", "Kotlin", "Go")
// firstXxx(正序遍历) lastXxx(倒序遍历)
// 返回数组第一个元素,若是空数组,则会抛异常
println(array.first()) //Java
// 返回满足条件的第一个元素,若都不满足条件,则会抛异常
println(array.first { it.length > 2 }) //Java
// 返回数组第一个元素,若是空数组,则返回 null
println(array.firstOrNull()) //Java
// 返回满足条件的第一个元素,若都不满足条件,则返回 null
println(array.firstOrNull { it.length > 6 }) //null
// 返回数组最后一个元素,若是空数组,则会抛异常
println(array.last()) //Go
// 返回满足条件的最后一个元素,若都不满足条件,则会抛异常
println(array.last { it.length > 2 }) //Kotlin
// 返回数组最后一个元素,若是空数组,则返回 null
println(array.lastOrNull()) //Go
// 返回满足条件的最后一个元素,若都不满足条件,则返回 null
println(array.lastOrNull { it.length > 6 }) //null
  1. 增值运算
    fold(initial: R, operation: (acc: R, T) -> R): R
    foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R
    foldRight(initial: R, operation: (T, acc: R) -> R): R
    foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R
    runningFold(initial: R, operation: (acc: R, T) -> R): List<R>
    runningFoldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): List<R>
val array = arrayOf("Java", "Kotlin", "Go")
// 将元素作为参数传入 operation 表达式后执行计算,将结果作为下一个数组的 initial,直到执行完所有元素,并返回最终值
// fold 正序遍历 acc:增值器,s:元素
println(array.fold("", { acc, s -> s + acc })) //GoKotlinJava
// foldIndexed 正序遍历 index:索引,acc:增值器,s:元素
println(array.foldIndexed("", { index, acc, s -> "$index$s$acc" })) //2Go1Kotlin0Java
// foldRight 倒序遍历 s:元素,acc:增值器
println(array.foldRight("", { s, acc -> s + acc })) //JavaKotlinGo
// foldRightIndexed 倒序遍历 index:索引,s:元素,acc:增值器
println(array.foldRightIndexed("", { index, s, acc -> "$index$s$acc" })) //0Java1Kotlin2Go
// runningFold 正序遍历 acc:增值器,s:元素 返回 List
println(array.runningFold("", { acc, s -> s + acc })) //[, Java, KotlinJava, GoKotlinJava]
// runningFoldIndexed 正序遍历 index:索引,acc:增值器,s:元素 返回 List
println(array.runningFoldIndexed("", { index, acc, s -> "$index$s$acc" })) //[, 0Java, 1Kotlin0Java, 2Go1Kotlin0Java]
  1. 获取元素的索引
    indexOf(element: T): Int
    lastIndexOf(element: T): Int
    indexOfFirst(predicate: (T) -> Boolean): Int
    indexOfLast(predicate: (T) -> Boolean): Int
val array = arrayOf("Java", "Kotlin", "Go")
// 正序/倒序搜索元素 element 在数组中的索引
println(array.indexOf("Java")) //0
println(array.lastIndexOf("Java")) //0
// 正序/倒序搜索元素,当满足条件时
println(array.indexOfFirst { it.isNotEmpty() }) //0
println(array.indexOfLast { it.isNotEmpty() }) //2
  1. 获取元素的交集或并集
    intersect(other: Iterable<T>): Set<T>
    union(other: Iterable<T>): Set<T>
val array = arrayOf("Java", "Kotlin", "Go")
val otherMutableList = mutableListOf("Java", "Swift", "C++")
// 获取两个数组的交集
println(array.intersect(otherMutableList)) //[Java]
// 获取两个数组的并集
println(array.union(otherMutableList)) //[Java, Kotlin, Go, Swift, C++]
  1. 添加元素或数组
    plus(element: T): Array<T>
    plusElement(element: T): Array<T>
    plus(elements: Collection<T>): Array<T>
val array = arrayOf("Java", "Kotlin", "Go")
// 添加元素或数组
println(array.plus("Dart").contentToString()) //[Java, Kotlin, Go, Dart]
println(array.plusElement("Dart").contentToString()) //[Java, Kotlin, Go, Dart]
println(array.plus(otherMutableList).contentToString()) //[Java, Kotlin, Go, Java, Swift, C++]
  1. 获取最大/最小值
    maxOrNull(): T?
    minOrNull(): T?
val array = arrayOf("Java", "Kotlin", "Go")
// 按照自然排序规则,获取数组中元素最大值/最小值
println(array.maxOrNull()) //Kotlin
println(array.minOrNull()) //Go
  1. 排序
    sort(): Unit
    sortWith(comparator: Comparator<in T>): Unit
val array = arrayOf("Java", "Kotlin", "Go")
// 数组排序,按自然排序
array.sort()
println(array.contentToString()) //[Go, Java, Kotlin]
// 数组排序,按自定义规则排序
array.sortWith { s1, s2 -> s2.length - s1.length }
println(array.contentToString()) //[Kotlin, Java, Go]

Array 的遍历

  1. for(item in array) { ... }
    for-in 遍历,遍历元素
  2. for(index in array.indices) { ... }
    for-in 遍历,遍历下标,indices 方法返回数组的索引区间
  3. for ((index, item) in array.withIndex()) { ... }
    withIndex() 方法返回一个 Iterable 对象,该对象的所有元素都是 IndexedValue
  4. array.forEach { ... }
    forEach Lambda 表达式遍历
val array1 = arrayOf("Java", "Kotlin", "Go")
// for-in 遍历,遍历元素
for (item in array1) {
    println(item)
}

// for-in 遍历,遍历下标
for (index in array1.indices) {
    println(array1[index])
}

// for-in 遍历,使用 withIndex
for ((index, item) in array1.withIndex()) {
    println("第 $index 个元素是 $item")
}

// forEach 遍历
array1.forEach {
    println(it)
}

多维数组

// 二维数组:所有元素都是一维数组,本质还是一维数组
val twoDimensionalArray = arrayOf(arrayOf(1, 2), arrayOf(3, 4), arrayOf(5, 6))
twoDimensionalArray.forEach {
    println(it.contentToString())
}
//[1, 2]
//[3, 4]
//[5, 6]

// 三维数组:所有元素都是二维数组,本质还是一维数组
val threeDimensionalArray = arrayOf(
    arrayOf(arrayOf(1, 2), arrayOf(3, 4), arrayOf(5, 6)),
    arrayOf(arrayOf(7, 8), arrayOf(9, 10), arrayOf(11, 12))
)
threeDimensionalArray.forEach {
    it.forEach { second ->
        println(second.contentToString())
    }
}
//[1, 2]
//[3, 4]
//[5, 6]
//[7, 8]
//[9, 10]
//[11, 12]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,667评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,361评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,700评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,027评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,988评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,230评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,705评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,366评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,496评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,405评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,453评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,725评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,803评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,015评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,514评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,111评论 2 341