Kotlin極簡教程:第5章 集合類(上)

原文鏈接:https://github.com/EasyKotlin

本章將介紹Kotlin標(biāo)準(zhǔn)庫中的集合類喳钟,我們將了解到它是如何擴(kuò)展的Java集合庫,使得寫代碼更加簡單容易茁肠。如果您熟悉Scala的集合庫,您會(huì)發(fā)現(xiàn)Kotlin跟Scala集合類庫的相似之處。

5.1 集合類是什么

5.1.2 集合類是一種數(shù)據(jù)結(jié)構(gòu)

在講 Kotlin 的集合類之前怠肋,為了更加深刻理解為什么要有集合類,以及集合類到底是怎么一回事淹朋,讓我們先來簡單回顧一下編程的本質(zhì):

數(shù)據(jù)結(jié)構(gòu) + 算法 (信息的邏輯結(jié)構(gòu)及其基本操作)

我們使用計(jì)算機(jī)編程來解決一個(gè)具體問題時(shí)笙各,大致需要經(jīng)過下列幾個(gè)步驟:

首先要從具體問題中抽象出一個(gè)適當(dāng)?shù)臄?shù)學(xué)模型;
然后設(shè)計(jì)一個(gè)解此數(shù)學(xué)模型的算法(Algorithm)础芍;
最后編出程序杈抢、進(jìn)行測(cè)試、修改直至得到最終解答仑性。

這里面的尋求數(shù)學(xué)模型的過程惶楼,實(shí)質(zhì)就是分析問題,從中提取操作的對(duì)象诊杆,并找出這些操作對(duì)象之間含有的關(guān)系的過程歼捐。建立好的模型,我們使用數(shù)學(xué)語言來表達(dá)晨汹。

這里的模型對(duì)應(yīng)的就是數(shù)據(jù)結(jié)構(gòu)豹储。我們用計(jì)算機(jī)編程來解決問題的關(guān)鍵就是,設(shè)計(jì)出合適的數(shù)據(jù)結(jié)構(gòu)(例如宰缤,用線性表颂翼、樹、圖等)和性能良好的算法慨灭。

算法與數(shù)據(jù)的結(jié)構(gòu)密切相關(guān)朦乏,算法無不依附于具體的數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu)直接關(guān)系到算法的選擇和效率氧骤。通常情況下呻疹,設(shè)計(jì)良好的數(shù)據(jù)結(jié)構(gòu)可以大大簡化算法的實(shí)現(xiàn)復(fù)雜度,同時(shí)可以提升存儲(chǔ)效率筹陵。數(shù)據(jù)結(jié)構(gòu)往往同高效的檢索算法和索引技術(shù)相關(guān)刽锤。

我們可以把數(shù)據(jù)結(jié)構(gòu)理解為是ADT的實(shí)現(xiàn)镊尺。數(shù)據(jù)結(jié)構(gòu)就是現(xiàn)實(shí)問題模型的表達(dá)。

數(shù)據(jù)結(jié)構(gòu)主要解決以下三個(gè)問題:

  • 數(shù)據(jù)元素之間的邏輯關(guān)系并思。

這些邏輯關(guān)系有:集合庐氮、線性結(jié)構(gòu)、樹形結(jié)構(gòu)宋彼、圖形結(jié)構(gòu)等弄砍。

  • 數(shù)據(jù)的物理結(jié)構(gòu)输涕。

數(shù)據(jù)的邏輯結(jié)構(gòu)在計(jì)算機(jī)存儲(chǔ)空間的存放形式音婶。數(shù)據(jù)的物理結(jié)構(gòu)是數(shù)據(jù)結(jié)構(gòu)在計(jì)算機(jī)中的映射。其具體實(shí)現(xiàn)的方法有: 順序(Sequence)莱坎、鏈接(Link)衣式、索引(Index)、散列(Hash)等形式檐什。

其中碴卧,順序存儲(chǔ)結(jié)構(gòu)和鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是我們常用的兩種存儲(chǔ)結(jié)構(gòu)。

順序存儲(chǔ)是使用元素在存儲(chǔ)器中的相對(duì)位置來表示數(shù)據(jù)元素之間的邏輯關(guān)系厢汹;

鏈?zhǔn)酱鎯?chǔ)使用指示元素存儲(chǔ)位置的指針(pointer)來表示數(shù)據(jù)元素之間的邏輯關(guān)系螟深。

  • 數(shù)據(jù)的處理運(yùn)算。

5.1.2 集合類是SDK API

我們現(xiàn)在很少用抽象數(shù)據(jù)類型ADT(Abstract Data Type)這個(gè)概念烫葬,其實(shí)這個(gè)概念是OO范式的前身界弧,也是類的前身。ADT加上繼承搭综、重載和多態(tài)性就是現(xiàn)代OOP編程范式中的類的概念了垢箕。我們簡稱類為廣義ADT的概念。

如果我們更加廣義的來理解這里的ADT的思想兑巾,其實(shí)各種編程語言的SDK API条获、所有的服務(wù)(IaaS,PaaS和SaaS等)都是一種更加廣義的ADT蒋歌。

使用ADT可以讓我們更簡單地描述現(xiàn)實(shí)世界帅掘。例如:用線性表描述學(xué)生成績表,用樹或圖描述遺傳關(guān)系等堂油。

我們知道類的本質(zhì)就是修档,對(duì)象及其關(guān)系的抽象(abstraction)。一個(gè)類通常有屬性(數(shù)據(jù)結(jié)構(gòu))和行為(算法)府框。使用OO范式編程的大致過程為:

劃分對(duì)象 → 抽象類 → 將類組織成為層次化結(jié)構(gòu)(繼承和合成) → 用類與實(shí)例進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)

等幾個(gè)階段吱窝。

數(shù)據(jù)抽象本質(zhì)上講就是我們解決現(xiàn)實(shí)問題的過程中,進(jìn)行建立領(lǐng)域模型(Domain Model)的過程。

比如說院峡,在前一章節(jié)中兴使,我們介紹的程序設(shè)計(jì)語言的類型系統(tǒng),本質(zhì)上就是一種數(shù)據(jù)抽象照激。由于計(jì)算機(jī)的結(jié)構(gòu)和存儲(chǔ)的限制(無法像人類大腦神經(jīng)系統(tǒng)一樣去認(rèn)知識(shí)別发魄,并解決現(xiàn)實(shí)問題),人類大腦在解決實(shí)際問題過程中俩垃,經(jīng)常要計(jì)算整數(shù)欠母、小數(shù), 要處理英文字符、中文字符吆寨, 要持有對(duì)象(被操作的數(shù)據(jù)),要對(duì)這些對(duì)象進(jìn)行諸如:查找踩寇、排序啄清、修改、傳遞等操作俺孙。把這些問題解決中最常用的數(shù)據(jù)結(jié)構(gòu)以及其操作算法抽象成對(duì)應(yīng)的類(例如:String辣卒、Array、List睛榄、Set荣茫、Map等),這樣我們就可以極大的復(fù)用這些功能场靴。而不需要我們自己來實(shí)現(xiàn)諸如:字符串啡莉、數(shù)組、列表旨剥、集合咧欣、映射等這些的數(shù)據(jù)結(jié)構(gòu)。通常這些最通用的數(shù)據(jù)結(jié)構(gòu)轨帜,都是現(xiàn)在編程語言中內(nèi)置的了魄咕。

5.1.3 連續(xù)存儲(chǔ)和離散存儲(chǔ)

內(nèi)存中的存儲(chǔ)形式可以分為連續(xù)存儲(chǔ)和離散存儲(chǔ)兩種。因此蚌父,數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)就有連續(xù)存儲(chǔ)和離散存儲(chǔ)兩種哮兰,它們對(duì)應(yīng)了我們通常所說的數(shù)組和鏈表。

由于數(shù)組是連續(xù)存儲(chǔ)的苟弛,在操作數(shù)組中的數(shù)據(jù)時(shí)就可以根據(jù)離首地址的偏移量直接存取相應(yīng)位置上的數(shù)據(jù)喝滞,但是如果要在數(shù)據(jù)組中任意位置上插入一個(gè)元素,就需要先把后面的元素集體向后移一位為其空出存儲(chǔ)空間嗡午。與之相反囤躁,鏈表是離散存儲(chǔ)的,所以在插入一個(gè)數(shù)據(jù)時(shí)只要申請(qǐng)一片新空間,然后將其中的連接關(guān)系做一個(gè)修改就可以狸演,但是顯然在鏈表上查找一個(gè)數(shù)據(jù)時(shí)就要逐個(gè)遍歷了言蛇。

考慮以上的總結(jié)可見,數(shù)組和鏈表各有優(yōu)缺點(diǎn)宵距。在具體使用時(shí)要根據(jù)具體情況選擇腊尚。當(dāng)查找數(shù)據(jù)操作比較多時(shí)最好用數(shù)組;當(dāng)對(duì)數(shù)據(jù)集中的數(shù)據(jù)進(jìn)行添加或刪除比較多時(shí)最好選擇鏈表满哪。

5.2 Kotlin 集合類簡介

集合類存放的都是對(duì)象的引用婿斥,而非對(duì)象本身,我們通常說的集合中的對(duì)象指的是集合中對(duì)象的引用(reference)哨鸭。

Kotlin的集合類分為:可變集合類(Mutable)與不可變集合類(Immutable)民宿。

集合類型主要有3種:list(列表)、set(集)像鸡、和 map(映射)活鹰。

(1)列表

列表的主要特征是其對(duì)象以線性方式存儲(chǔ),沒有特定順序只估,只有一個(gè)開頭和一個(gè)結(jié)尾志群,當(dāng)然,它與根本沒有順序的集是不同的蛔钙。

列表在數(shù)據(jù)結(jié)構(gòu)中可表現(xiàn)為:數(shù)組和向量锌云、鏈表、堆棧吁脱、隊(duì)列等桑涎。

(2)集

集(set)是最簡單的一種集合,它的對(duì)象不按特定方式排序豫喧,只是簡單的把對(duì)象加入集合中石洗,就像往口袋里放東西。

對(duì)集中成員的訪問和操作是通過集中對(duì)象的引用進(jìn)行的紧显,所以集中不能有重復(fù)對(duì)象讲衫。

集也有多種變體,可以實(shí)現(xiàn)排序等功能孵班,如TreeSet涉兽,它把對(duì)象添加到集中的操作將變?yōu)榘凑漳撤N比較規(guī)則將其插入到有序的對(duì)象序列中。它實(shí)現(xiàn)的是SortedSet接口篙程,也就是加入了對(duì)象比較的方法枷畏。通過對(duì)集中的對(duì)象迭代,我們可以得到一個(gè)升序的對(duì)象集合虱饿。

(3)映射

映射與集或列表有明顯區(qū)別拥诡,映射中每個(gè)項(xiàng)都是成對(duì)的触趴。映射中存儲(chǔ)的每個(gè)對(duì)象都有一個(gè)相關(guān)的關(guān)鍵字(Key)對(duì)象,關(guān)鍵字決定了 對(duì)象在映射中的存儲(chǔ)位置渴肉,檢索對(duì)象時(shí)必須提供相應(yīng)的關(guān)鍵字冗懦,就像在字典中查單詞一樣。關(guān)鍵字應(yīng)該是唯一的仇祭。

關(guān)鍵字本身并不能決定對(duì)象的存儲(chǔ)位置披蕉,它需要對(duì)過一種散列(hashing)技術(shù)來處理,產(chǎn)生一個(gè)被稱作散列碼(hash code)的整數(shù)值乌奇,

散列碼通常用作一個(gè)偏置量没讲,該偏置量是相對(duì)于分配給映射的內(nèi)存區(qū)域起始位置的,由此確定關(guān)鍵字/對(duì)象對(duì)的存儲(chǔ)位置礁苗。理想情況 下爬凑,散列處理應(yīng)該產(chǎn)生給定范圍內(nèi)均勻分布的值,而且每個(gè)關(guān)鍵字應(yīng)得到不同的散列碼试伙。

5.3 List

List接口繼承于Collection接口贰谣,元素以線性方式存儲(chǔ),集合中可以存放重復(fù)對(duì)象迁霎。Kotlin的List分為:不可變集合類List(ReadOnly, Immutable)和可變集合類MutableList(Read&Write, Mutable)。

其類圖結(jié)構(gòu)如下:

img
img

其中百宇,Iterator是所有容器類Collection的迭代器考廉。迭代器(Iterator)模式,又叫做游標(biāo)(Cursor)模式携御。GOF給出的定義為:提供一種方法訪問一個(gè)容器對(duì)象中各個(gè)元素昌粤,而又不需暴露該對(duì)象的內(nèi)部細(xì)節(jié)。 從定義可見啄刹,迭代器模式是為容器而生涮坐。

5.3.1 創(chuàng)建不可變List

我們可以使用listOf函數(shù)來構(gòu)建一個(gè)不可變的List(read-only,只讀的List)誓军。它定義在libraries/stdlib/src/kotlin/collections/Collections.kt 里面袱讹。關(guān)于listOf這個(gè)構(gòu)建函數(shù)有下面3個(gè)重載函數(shù):

@kotlin.internal.InlineOnly
public inline fun <T> listOf(): List<T> = emptyList()

public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

@JvmVersion
public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element)

這些函數(shù)創(chuàng)建的List都是是只讀的(readonly,也就是不可變的immutable )昵时、可序列化的捷雕。

其中,

  • listOf()用于創(chuàng)建沒有元素的空List
  • listOf(vararg elements: T)用于創(chuàng)建只有一個(gè)元素的List
  • listOf(element: T)用于創(chuàng)建擁有多個(gè)元素的List

我們使用代碼示例分別來演示其用法:

首先壹甥,我們使用listOf()來構(gòu)建一個(gè)沒有元素的空的List:

>>> val list:List<Int> = listOf()
>>> list
[]
>>> list::class
class kotlin.collections.EmptyList

注意救巷,這里的變量的類型不能省略,否則會(huì)報(bào)錯(cuò):

>>> val list = listOf()
error: type inference failed: Not enough information to infer parameter T in inline fun <T> listOf(): List<T>
Please specify it explicitly.

val list = listOf()
           ^

因?yàn)檫@是一個(gè)泛型函數(shù)句柠。關(guān)于泛型浦译,我們將在下一章中介紹棒假。

其中,EmptyList 是一個(gè) internal object EmptyList, 這是Kotlin內(nèi)部定義的一個(gè)默認(rèn)空的object List類精盅。

下面帽哑,我們?cè)賮韯?chuàng)建一個(gè)只有1個(gè)元素的List:

>>> val list = listOf(1)
>>> list::class
class java.util.Collections$SingletonList

我們可以看出,它實(shí)際上是調(diào)用Java的java.util.Collections 里面的singletonList方法:

public static <T> List<T> singletonList(T o) {
    return new SingletonList<>(o);
}

我們?cè)賮韯?chuàng)建一個(gè)有多個(gè)元素的List:

>>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
>>> list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list::class
class java.util.Arrays$ArrayList
>>> list::class.java

它調(diào)用的是

fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

這個(gè)函數(shù)渤弛。其中祝拯,asList函數(shù)是Array的擴(kuò)展函數(shù):

public fun <T> Array<out T>.asList(): List<T> {
    return ArraysUtilJVM.asList(this)
}

而這個(gè)ArraysUtilJVM是一個(gè)Java類,里面實(shí)際上調(diào)用的是java.util.Arraysjava.util.List :

package kotlin.collections;

import java.util.Arrays;
import java.util.List;

class ArraysUtilJVM {
    static <T> List<T> asList(T[] array) {
        return Arrays.asList(array);
    }
}

另外她肯,我們還可以直接使用arrayListOf函數(shù)來創(chuàng)建一個(gè)Java中的ArrayList對(duì)象實(shí)例:

>>> val list = arrayListOf(0,1,2,3)
>>> list
[0, 1, 2, 3]
>>> list::class
class java.util.ArrayList
>>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9) 
>>> list::class
class java.util.Arrays$ArrayList

這個(gè)函數(shù)定義在libraries/stdlib/src/kotlin/collections/Collections.kt類中:

@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList()

同樣的處理方式佳头,這里的ArrayList()是Java中的java.util.ArrayList的類型別名:

@SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>

5.3.2 創(chuàng)建可變集合MutableList

在MutableList中,除了繼承List中的那些函數(shù)外晴氨,另外新增了add/addAll康嘉、remove/removeAll/removeAt、set籽前、clear亭珍、retainAll等更新修改的操作函數(shù)。

override fun add(element: E): Boolean
override fun remove(element: E): Boolean
override fun addAll(elements: Collection<E>): Boolean
fun addAll(index: Int, elements: Collection<E>): Boolean
override fun removeAll(elements: Collection<E>): Boolean
override fun retainAll(elements: Collection<E>): Boolean
override fun clear(): Unit
operator fun set(index: Int, element: E): E
fun add(index: Int, element: E): Unit
fun removeAt(index: Int): E
override fun listIterator(): MutableListIterator<E>
override fun listIterator(index: Int): MutableListIterator<E>
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>

創(chuàng)建一個(gè)MutableList的對(duì)象實(shí)例跟List類似枝哄,前面加上前綴mutable肄梨,代碼示例如下:

>>> val list = mutableListOf(1, 2, 3)
>>> list
[1, 2, 3]
>>> list::class
class java.util.ArrayList
>>> val list2 = mutableListOf<Int>()
>>> list2
[]
>>> list2::class
class java.util.ArrayList
>>> val list3 = mutableListOf(1)
>>> list3
[1]
>>> list3::class
class java.util.ArrayList

我們可以看出,使用mutableListOf函數(shù)創(chuàng)建的可變集合類挠锥,實(shí)際上背后調(diào)用的是java.util.ArrayList類的相關(guān)方法众羡。

另外,我們可以直接使用Kotlin封裝的arrayListOf函數(shù)來創(chuàng)建一個(gè)ArrayList:

>>> val list4 = arrayListOf(1, 2, 3)
>>> list4::class
class java.util.ArrayList

關(guān)于Kotlin中的ArrayList類型別名定義在
kotlin/collections/TypeAliases.kt 文件中:

@file:kotlin.jvm.JvmVersion

package kotlin.collections

@SinceKotlin("1.1") public typealias RandomAccess = java.util.RandomAccess


@SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>
@SinceKotlin("1.1") public typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
@SinceKotlin("1.1") public typealias HashMap<K, V> = java.util.HashMap<K, V>
@SinceKotlin("1.1") public typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
@SinceKotlin("1.1") public typealias HashSet<E> = java.util.HashSet<E>


// also @SinceKotlin("1.1")
internal typealias SortedSet<E> = java.util.SortedSet<E>
internal typealias TreeSet<E> = java.util.TreeSet<E>

如果我們已經(jīng)有了一個(gè)不可變的List蓖租,而我們現(xiàn)在想把他轉(zhuǎn)換成可變的List粱侣,我們可以直接調(diào)用轉(zhuǎn)換函數(shù)toMutableList

val list = mutableListOf(1, 2, 3)
val mlist = list.toMutableList()
mlist.add(5)

5.3.3 遍歷List元素

使用Iterator迭代器

我們以集合 val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)為例,使用Iterator迭代器遍歷列表所有元素的操作:

>>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9) 
>>> list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> val iterator = list.iterator()
>>> iterator
java.util.AbstractList$Itr@438bad7c
>>> while(iterator.hasNext()){
... println(iterator.next())
... }
0
1
2
3
4
5
6
7
8
9

迭代器是一種設(shè)計(jì)模式蓖宦,它是一個(gè)對(duì)象齐婴,它可以遍歷并選擇序列中的對(duì)象,而開發(fā)人員不需要了解該序列的底層結(jié)構(gòu)稠茂。迭代器通常被稱為“輕量級(jí)”對(duì)象柠偶,因?yàn)閯?chuàng)建它的代價(jià)小。

Kotlin中的Iterator功能比較簡單睬关,并且只能單向移動(dòng):

(1)調(diào)用iterator()函數(shù)嚣州,容器返回一個(gè)Iterator實(shí)例。iterator()函數(shù)是kotlin.collections.Iterable中的函數(shù), 被Collection繼承共螺。
(2)調(diào)用hasNext()函數(shù)檢查序列中是否還有元素该肴。
(3)第一次調(diào)用Iterator的next()函數(shù)時(shí),它返回序列的第一個(gè)元素藐不。依次向后遞推匀哄,使用next()獲得序列中的下一個(gè)元素秦效。

當(dāng)我們調(diào)用到最后一個(gè)元素,再次調(diào)用next()函數(shù)涎嚼,會(huì)拋這個(gè)異常java.util.NoSuchElementException阱州。代碼示例:

>>> val list = listOf(1,2,3)
>>> val iter = list.iterator()
>>> iter
java.util.AbstractList$Itr@3abfe845
>>> iter.hasNext()
true
>>> iter.next()
1
>>> iter.hasNext()
true
>>> iter.next()
2
>>> iter.hasNext()
true
>>> iter.next()
3
>>> iter.hasNext()
false
>>> iter.next()
java.util.NoSuchElementException
    at java.util.AbstractList$Itr.next(AbstractList.java:364)

我們可以看出,這里的Iterator的實(shí)現(xiàn)是在AbstractList中的內(nèi)部類IteratorImpl

private open inner class IteratorImpl : Iterator<E> {
    protected var index = 0
    override fun hasNext(): Boolean = index < size
    override fun next(): E {
        if (!hasNext()) throw NoSuchElementException()
        return get(index++)
    }
}

通過這個(gè)實(shí)現(xiàn)源碼法梯,我們可以更加清楚地明白Iterator的工作原理苔货。

其中,NoSuchElementException()這個(gè)類是java.util.NoSuchElementException的類型別名:

@kotlin.SinceKotlin public typealias NoSuchElementException = java.util.NoSuchElementException

使用forEach遍歷List元素

這個(gè)forEach函數(shù)定義如下:

@kotlin.internal.HidesMembers
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

它是package kotlin.collections包下面的Iterable的擴(kuò)展內(nèi)聯(lián)函數(shù)立哑。它的入?yún)⑹且粋€(gè)函數(shù)類型:

action: (T) -> Unit

關(guān)于函數(shù)式編程夜惭,我們將在后面章節(jié)中學(xué)習(xí)。

這里的forEach是一個(gè)語法糖铛绰。實(shí)際上forEach在遍歷List對(duì)象的時(shí)候诈茧,仍然使用的是iterator迭代器來進(jìn)行循環(huán)遍歷的。

>>> val list = listOf(1,2,3)
>>> list
[1, 2, 3]
>>> list.forEach{
... println(it)
... }
1
2
3

當(dāng)參數(shù)只有一個(gè)函數(shù)的時(shí)候捂掰,括號(hào)可以省略不寫敢会。

也就是說,這里面的forEach函數(shù)調(diào)用的寫法这嚣,實(shí)際上跟下面的寫法等價(jià):

list.forEach({
    println(it)
})

我們甚至還可以直接這樣寫:

>>> list.forEach(::println)

其中鸥昏,:: 是函數(shù)引用符。

5.3.4 List元素操作函數(shù)

add remove set clear

這兩個(gè)添加姐帚、刪除操作函數(shù)是MutableList里面的互广。跟Java中的集合類操作類似。

創(chuàng)建一個(gè)可變集合:

>>> val mutableList = mutableListOf(1,2,3)
>>> mutableList
[1, 2, 3]

向集合中添加一個(gè)元素:

>>> mutableList.add(4)
true
>>> mutableList
[1, 2, 3, 4]

在下標(biāo)為0的位置添加元素0 :

>>> mutableList.add(0,0)
>>> mutableList
[0, 1, 2, 3, 4]

刪除元素1 :

>>> mutableList.remove(1)
true
>>> mutableList
[0, 2, 3, 4]
>>> mutableList.remove(1)
false

刪除下標(biāo)為1的元素:

>>> mutableList.removeAt(1)
2
>>> mutableList
[0, 3, 4]

刪除子集合:

>>> mutableList.removeAll(listOf(3,4))
true
>>> mutableList
[0]

添加子集合:

>>> mutableList.addAll(listOf(1,2,3))
true
>>> mutableList
[1, 2, 3]

更新設(shè)置下標(biāo)0的元素值為100:

>>> mutableList.set(0,100)
0
>>> mutableList
[100]

清空集合:

>>> mutableList.clear()
>>> mutableList
[]

把可變集合轉(zhuǎn)為不可變集合:

>>> mutableList.toList()
[1, 2, 3]

retainAll

取兩個(gè)集合交集:

>>> val mlist1 = mutableListOf(1,2,3,4,5,6)
>>> val mlist2 = mutableListOf(3,4,5,6,7,8,9)
>>> mlist1.retainAll(mlist2)
true
>>> mlist1
[3, 4, 5, 6]

contains(element: T): Boolean

判斷集合中是否有指定元素卧土,有就返回true,否則返回false 像樊。
代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7)
>>> list.contains(1)
true

elementAt(index: Int): T

查找下標(biāo)對(duì)應(yīng)的元素尤莺,如果下標(biāo)越界會(huì)拋IndexOutOfBoundsException。
代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7)
>>> list.elementAt(6)
7
>>> list.elementAt(7)
java.lang.ArrayIndexOutOfBoundsException: 7
    at java.util.Arrays$ArrayList.get(Arrays.java:3841)

另外生棍,針對(duì)越界的處理颤霎,還有下面兩個(gè)函數(shù):

elementAtOrElse(index: Int, defaultValue: (Int) -> T): T : 查找下標(biāo)對(duì)應(yīng)元素,如果越界會(huì)根據(jù)方法返回默認(rèn)值涂滴。

>>> list.elementAtOrElse(7,{0})
0
>>> list.elementAtOrElse(7,{10})
10

elementAtOrNull(index: Int): T? : 查找下標(biāo)對(duì)應(yīng)元素友酱,如果越界就返回null

>>> list.elementAtOrNull(7)
null

first()

返回集合第1個(gè)元素,如果是空集柔纵,拋出異常NoSuchElementException缔杉。

>>> val list = listOf(1,2,3)
>>> list.first()
1
>>> val emptyList = listOf<Int>()
>>> emptyList.first()
java.util.NoSuchElementException: List is empty.
    at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:178)


對(duì)應(yīng)的有針對(duì)異常處理的函數(shù)firstOrNull(): T? :

>>> emptyList.firstOrNull()
null

first(predicate: (T) -> Boolean): T

返回符合條件的第一個(gè)元素,沒有則拋異常NoSuchElementException 搁料。

>>> val list = listOf(1,2,3)
>>> list.first({it%2==0})
2
>>> list.first({it>100})
java.util.NoSuchElementException: Collection contains no element matching the predicate.

對(duì)應(yīng)的有針對(duì)異常處理的函數(shù)firstOrNull(predicate: (T) -> Boolean): T? 或详,返回符合條件的第一個(gè)元素系羞,沒有就返回null :

>>> list.firstOrNull({it>100})
null

indexOf(element: T): Int

返回指定下標(biāo)的元素,沒有就返回-1

>>> val list = listOf("a","b","c")
>>> list.indexOf("c")
2
>>> list.indexOf("x")
-1

indexOfFirst(predicate: (T) -> Boolean): Int

返回第一個(gè)符合條件的元素下標(biāo)霸琴,沒有就返回-1 椒振。

>>> val list = listOf("abc","xyz","xjk","pqk")
>>> list.indexOfFirst({it.contains("x")})
1
>>> list.indexOfFirst({it.contains("k")})
2
>>> list.indexOfFirst({it.contains("e")})
-1

indexOfLast(predicate: (T) -> Boolean): Int

返回最后一個(gè)符合條件的元素下標(biāo),沒有就返回-1 梧乘。

>>> val list = listOf("abc","xyz","xjk","pqk")
>>> list.indexOfLast({it.contains("x")})
2
>>> list.indexOfLast({it.contains("k")})
3
>>> list.indexOfLast({it.contains("e")})
-1

last()

返回集合最后一個(gè)元素澎迎,空集則拋出異常NoSuchElementException。

>>> val list = listOf(1,2,3,4,7,5,6,7,8)
>>> list.last()
8
>>> val emptyList = listOf<Int>()
>>> emptyList.last()
java.util.NoSuchElementException: List is empty.
    at kotlin.collections.CollectionsKt___CollectionsKt.last(_Collections.kt:340)

last(predicate: (T) -> Boolean): T

返回符合條件的最后一個(gè)元素选调,沒有就拋NoSuchElementException

>>> val list = listOf(1,2,3,4,7,5,6,7,8)
>>> list.last({it==7})
7
>>> list.last({it>10})
java.util.NoSuchElementException: List contains no element matching the predicate.

對(duì)應(yīng)的針對(duì)越界處理的lastOrNull函數(shù):返回符合條件的最后一個(gè)元素夹供,沒有則返回null :

>>> list.lastOrNull({it>10})
null

lastIndexOf(element: T): Int

返回符合條件的最后一個(gè)元素,沒有就返回-1

>>> val list = listOf("abc","dfg","jkl","abc","bbc","wer")
>>> list.lastIndexOf("abc")
3

single(): T

該集合如果只有1個(gè)元素学歧,則返回該元素罩引。否則奈搜,拋異常接校。

>>> val list = listOf(1)
>>> list.single()
1

>>> val list = listOf(1,2)
>>> list.single()
java.lang.IllegalArgumentException: List has more than one element.
    at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:471)

>>> val list = listOf<Int>()

>>> list.single()
java.util.NoSuchElementException: List is empty.
    at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:469)

single(predicate: (T) -> Boolean): T

返回符合條件的單個(gè)元素,如有沒有符合的拋異常NoSuchElementException淘衙,或超過一個(gè)的拋異常IllegalArgumentException横浑。

>>> val list = listOf(1,2,3,4,7,5,6,7,8)
>>> list.single({it==1})
1
>>> list.single({it==7})
java.lang.IllegalArgumentException: Collection contains more than one matching element.

>>> list.single({it==10})
java.util.NoSuchElementException: Collection contains no element matching the predicate.

對(duì)應(yīng)的針對(duì)異常處理的函數(shù)singleOrNull: 返回符合條件的單個(gè)元素剔桨,如有沒有符合或超過一個(gè),返回null

>>> list.singleOrNull({it==7})
null
>>> list.singleOrNull({it==10})
null

5.3.5 List集合類的any all ``none ``count ``reduce ``fold ``max ``min sum 函數(shù)算子(operator)

any()判斷集合至少有一個(gè)元素

這個(gè)函數(shù)定義如下:

public fun <T> Iterable<T>.any(): Boolean {
    for (element in this) return true
    return false
}

如果該集合至少有一個(gè)元素徙融,返回true洒缀,否則返回false

代碼示例:

>>> val emptyList = listOf<Int>()
>>> emptyList.any()
false
>>> val list1 = listOf(1)
>>> list1.any()
true

any(predicate: (T) -> Boolean) 判斷集合中是否有滿足條件的元素

這個(gè)函數(shù)定義如下:

public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
    for (element in this) if (predicate(element)) return true
    return false
}

如果該集合中至少有一個(gè)元素匹配謂詞函數(shù)參數(shù)predicate: (T) -> Boolean欺冀,返回true树绩,否則返回false。

代碼示例:

>>> val list = listOf(1, 2, 3)
>>> list.any() // 至少有1個(gè)元素
true
>>> list.any({it%2==0}) // 元素2滿足{it%2==0}
true
>>> list.any({it>4}) // 沒有元素滿足{it>4}
false

all(predicate: (T) -> Boolean) 判斷集合中的元素是否都滿足條件

函數(shù)定義:

public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean {
    for (element in this) if (!predicate(element)) return false
    return true
}

當(dāng)且僅當(dāng)該集合中所有元素都滿足條件時(shí)隐轩,返回true饺饭;否則都返回false

代碼示例:

>>> val list = listOf(0,2,4,6,8)
>>> list.all({it%2==0})
true
>>> list.all({it>2})
false

none()判斷集合無元素

函數(shù)定義:

public fun <T> Iterable<T>.none(): Boolean {
    for (element in this) return false
    return true
}

如果該集合沒有任何元素职车,返回true瘫俊,否則返回false

代碼示例:

>>> val list = listOf<Int>()
>>> list.none()
true

none(predicate: (T) -> Boolean)判斷集合中所有元素都不滿足條件

函數(shù)定義:

public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean {
    for (element in this) if (predicate(element)) return false
    return true
}

當(dāng)且僅當(dāng)集合中所有元素都不滿足條件時(shí)返回true悴灵,否則返回false扛芽。

代碼示例:

>>> val list = listOf(0,2,4,6,8)
>>> list.none({it%2==1})
true
>>> list.none({it>0})
false

count() 計(jì)算集合中元素的個(gè)數(shù)

函數(shù)定義:

public fun <T> Iterable<T>.count(): Int {
    var count = 0
    for (element in this) count++
    return count
}

代碼示例:

>>> val list = listOf(0,2,4,6,8,9)
>>> list.count()
6

count(predicate: (T) -> Boolean) 計(jì)算集合中滿足條件的元素的個(gè)數(shù)

函數(shù)定義:

public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
    var count = 0
    for (element in this) if (predicate(element)) count++
    return count
}

代碼示例:

>>> val list = listOf(0,2,4,6,8,9)
>>> list.count()
6
>>> list.count({it%2==0})
5

reduce從 第一項(xiàng)到最后一項(xiàng)進(jìn)行累計(jì)運(yùn)算

函數(shù)定義:

public inline fun <S, T: S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

首先把第一個(gè)元素賦值給累加子accumulator,然后逐次向后取元素累加积瞒,新值繼續(xù)賦值給累加子accumulator = operation(accumulator, iterator.next())川尖,以此類推。最后返回累加子的值茫孔。

代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7,8,9)
>>> list.reduce({sum, next->sum+next})
45
>>> list.reduce({sum, next->sum*next})
362880
>>> val list = listOf("a","b","c")
>>> list.reduce({total, s->total+s})
abc

reduceRight從最后一項(xiàng)到第一項(xiàng)進(jìn)行累計(jì)運(yùn)算

函數(shù)定義:

public inline fun <S, T: S> List<T>.reduceRight(operation: (T, acc: S) -> S): S {
    val iterator = listIterator(size)
    if (!iterator.hasPrevious())
        throw UnsupportedOperationException("Empty list can't be reduced.")
    var accumulator: S = iterator.previous()
    while (iterator.hasPrevious()) {
        accumulator = operation(iterator.previous(), accumulator)
    }
    return accumulator
}

從函數(shù)的定義accumulator = operation(iterator.previous(), accumulator), 我們可以看出空厌,從右邊累計(jì)運(yùn)算的累加子是放在后面的庐船。

代碼示例:

>>> val list = listOf("a","b","c")
>>> list.reduceRight({total, s -> s+total})
cba

如果我們位置放錯(cuò)了,會(huì)輸出下面的結(jié)果:

>>> list.reduceRight({total, s -> total+s})
abc

fold(initial: R, operation: (acc: R, T) -> R): R 帶初始值的reduce

函數(shù)定義:

public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
    var accumulator = initial
    for (element in this) accumulator = operation(accumulator, element)
    return accumulator
}

從函數(shù)的定義嘲更,我們可以看出筐钟,fold函數(shù)給累加子賦了初始值initial

代碼示例:

>>> val list=listOf(1,2,3,4)
>>> list.fold(100,{total, next -> next + total})
110

foldRightreduceRight類似赋朦,有初始值篓冲。

函數(shù)定義:

public inline fun <T, R> List<T>.foldRight(initial: R, operation: (T, acc: R) -> R): R {
    var accumulator = initial
    if (!isEmpty()) {
        val iterator = listIterator(size)
        while (iterator.hasPrevious()) {
            accumulator = operation(iterator.previous(), accumulator)
        }
    }
    return accumulator
}

代碼示例:

>>> val list = listOf("a","b","c")
>>> list.foldRight("xyz",{s, pre -> pre + s})
xyzcba

forEach(action: (T) -> Unit): Unit 循環(huán)遍歷元素,元素是it

我們?cè)谇拔囊呀?jīng)講述宠哄,參看5.3.4壹将。

再寫個(gè)代碼示例:

>>> val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 
>>> list.forEach { value -> if (value > 7) println(value) } 
8
9

forEachIndexed 帶index(下標(biāo)) 的元素遍歷

函數(shù)定義:

public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
    var index = 0
    for (item in this) action(index++, item)
}

代碼示例:

>>> val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 
>>> list.forEachIndexed { index, value -> if (value > 8) println("value of index $index is $value, greater than 8") } 

value of index 9 is 9, greater than 8

maxmin查詢最大毛嫉、最小的元素诽俯,空集則返回null

max函數(shù)定義:

public fun <T : Comparable<T>> Iterable<T>.max(): T? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    var max = iterator.next()
    while (iterator.hasNext()) {
        val e = iterator.next()
        if (max < e) max = e
    }
    return max
}

返回集合中最大的元素。

代碼示例:

>>> val list = listOf(1,2,3)
>>> list.max()
3
>>> val list = listOf("a","b","c")
>>> list.max()
c

min函數(shù)定義:

public fun <T : Comparable<T>> Iterable<T>.min(): T? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    var min = iterator.next()
    while (iterator.hasNext()) {
        val e = iterator.next()
        if (min > e) min = e
    }
    return min
}

返回集合中的最小元素承粤。

代碼示例:

>>> val list = listOf(1,2,3)
>>> list.min()
1
>>> val list = listOf("a","b","c")
>>> list.min()
a

在Kotlin中暴区,字符串的大小比較比較有意思的,我們直接通過代碼示例來學(xué)習(xí)一下:

>>> "c" > "a"
true
>>> "abd" > "abc"
true
>>> "abd" > "abcd"
true
>>> "abd" > "abcdefg"
true

我們可以看出辛臊,字符串的大小比較是按照對(duì)應(yīng)的下標(biāo)的字符進(jìn)行比較的仙粱。
另外,布爾值的比較是true大于false

>>> true > false
true

maxBy(selector: (T) -> R): T? 彻舰、 minBy(selector: (T) -> R): T?獲取函數(shù)映射結(jié)果的最大值伐割、最小值對(duì)應(yīng)的那個(gè)元素的值,如果沒有則返回null

函數(shù)定義:

public inline fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    var maxElem = iterator.next()
    var maxValue = selector(maxElem)
    while (iterator.hasNext()) {
        val e = iterator.next()
        val v = selector(e)
        if (maxValue < v) {
            maxElem = e
            maxValue = v
        }
    }
    return maxElem
}

也就是說刃唤,不直接比較集合元素的大小隔心,而是以集合元素為入?yún)⒌暮瘮?shù)selector: (T) -> R 返回值來比較大小,最后返回此元素的值(注意尚胞,不是對(duì)應(yīng)的selector函數(shù)的返回值)硬霍。有點(diǎn)像數(shù)學(xué)里的求函數(shù)最值問題:

給定函數(shù) y = f(x) , 求max f(x)x的值辐真。

代碼示例:

>>> val list = listOf(100,-500,300,200)
>>> list.maxBy({it})
300
>>> list.maxBy({it*(1-it)})
100
>>> list.maxBy({it*it})
-500

對(duì)應(yīng)的 minBy 是獲取函數(shù)映射后返回結(jié)果的最小值所對(duì)應(yīng)那個(gè)元素的值,如果沒有則返回null崖堤。

代碼示例:

>>> val list = listOf(100,-500,300,200)
>>> list.minBy({it})
-500
>>> list.minBy({it*(1-it)})
-500
>>> list.minBy({it*it})
100

sumBy(selector: (T) -> Int): Int 獲取函數(shù)映射值的總和

函數(shù)定義:

public inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int {
    var sum: Int = 0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}

可以看出侍咱,這個(gè)sumBy函數(shù)算子,累加器sum初始值為0密幔,返回值是Int楔脯。它的入?yún)?code>selector是一個(gè)函數(shù)類型(T) -> Int,也就是說這個(gè)selector也是返回Int類型的函數(shù)胯甩。

代碼示例:

>>> val list = listOf(1,2,3,4)
>>> list.sumBy({it})
10
>>> list.sumBy({it*it})
30

類型錯(cuò)誤反例:

>>> val list = listOf("a","b","c")
>>> list.sumBy({it})
error: type inference failed: inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int
cannot be applied to
receiver: List<String>  arguments: ((String) -> String)

list.sumBy({it})
     ^
error: type mismatch: inferred type is (String) -> String but (String) -> Int was expected
list.sumBy({it})
           ^

5.3.6 過濾操作函數(shù)算子

take(n: Int): List<T> 挑出該集合前n個(gè)元素的子集合

函數(shù)定義:

public fun <T> Iterable<T>.take(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    if (n == 0) return emptyList()
    if (this is Collection<T>) {
        if (n >= size) return toList()
        if (n == 1) return listOf(first())
    }
    var count = 0
    val list = ArrayList<T>(n)
    for (item in this) {
        if (count++ == n)
            break
        list.add(item)
    }
    return list.optimizeReadOnlyList()
}

如果n等于0昧廷,返回空集堪嫂;如果n大于集合size,返回該集合木柬。

代碼示例:

>>> val list = listOf("a","b","c")
>>> list
[a, b, c]
>>> list.take(2)
[a, b]
>>> list.take(10)
[a, b, c]
>>> list.take(0)
[]

takeWhile(predicate: (T) -> Boolean): List<T> 挑出滿足條件的元素的子集合

函數(shù)定義:

public inline fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T> {
    val list = ArrayList<T>()
    for (item in this) {
        if (!predicate(item))
            break
        list.add(item)
    }
    return list
}

從第一個(gè)元素開始皆串,判斷是否滿足predicate為true,如果滿足條件的元素就丟到返回ArrayList中眉枕。只要遇到任何一個(gè)元素不滿足條件恶复,就結(jié)束循環(huán),返回list 速挑。

代碼示例:

>>> val list = listOf(1,2,4,6,8,9)
>>> list.takeWhile({it%2==0})
[]
>>> list.takeWhile({it%2==1})
[1]

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.takeWhile({it%2==0})
[2, 4, 6, 8]

takeLast 挑出后n個(gè)元素的子集合

函數(shù)定義:

public fun <T> List<T>.takeLast(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    if (n == 0) return emptyList()
    val size = size
    if (n >= size) return toList()
    if (n == 1) return listOf(last())
    val list = ArrayList<T>(n)
    if (this is RandomAccess) {
        for (index in size - n .. size - 1)
            list.add(this[index])
    } else {
        for (item in listIterator(n))
            list.add(item)
    }
    return list
}

從集合倒數(shù)n個(gè)元素起谤牡,取出到最后一個(gè)元素的子集合。如果傳入0姥宝,返回空集翅萤。如果傳入n大于集合size,返回整個(gè)集合腊满。如果傳入負(fù)數(shù)套么,直接拋出IllegalArgumentException。

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.takeLast(0)
[]
>>> list.takeLast(3)
[11, 12, 16]
>>> list.takeLast(100)
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.takeLast(-1)
java.lang.IllegalArgumentException: Requested element count -1 is less than zero.
    at kotlin.collections.CollectionsKt___CollectionsKt.takeLast(_Collections.kt:734)

takeLastWhile(predicate: (T) -> Boolean) 從最后開始挑出滿足條件元素的子集合

函數(shù)定義:

public inline fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean): List<T> {
    if (isEmpty())
        return emptyList()
    val iterator = listIterator(size)
    while (iterator.hasPrevious()) {
        if (!predicate(iterator.previous())) {
            iterator.next()
            val expectedSize = size - iterator.nextIndex()
            if (expectedSize == 0) return emptyList()
            return ArrayList<T>(expectedSize).apply {
                while (iterator.hasNext())
                    add(iterator.next())
            }
        }
    }
    return toList()
}

反方向取滿足條件的元素糜烹,遇到不滿足的元素违诗,直接終止循環(huán),并返回子集合疮蹦。

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.takeLastWhile({it%2==0})
[12, 16]

drop(n: Int) 去除前n個(gè)元素返回剩下的元素的子集合

函數(shù)定義:

public fun <T> Iterable<T>.drop(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    if (n == 0) return toList()
    val list: ArrayList<T>
    if (this is Collection<*>) {
        val resultSize = size - n
        if (resultSize <= 0)
            return emptyList()
        if (resultSize == 1)
            return listOf(last())
        list = ArrayList<T>(resultSize)
        if (this is List<T>) {
            if (this is RandomAccess) {
                for (index in n..size - 1)
                    list.add(this[index])
            } else {
                for (item in listIterator(n))
                    list.add(item)
            }
            return list
        }
    }
    else {
        list = ArrayList<T>()
    }
    var count = 0
    for (item in this) {
        if (count++ >= n) list.add(item)
    }
    return list.optimizeReadOnlyList()
}

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.drop(5)
[11, 12, 16]
>>> list.drop(100)
[]
>>> list.drop(0)
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.drop(-1)
java.lang.IllegalArgumentException: Requested element count -1 is less than zero.
    at kotlin.collections.CollectionsKt___CollectionsKt.drop(_Collections.kt:538)

dropWhile(predicate: (T) -> Boolean) 去除滿足條件的元素返回剩下的元素的子集合

函數(shù)定義:

public inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T> {
    var yielding = false
    val list = ArrayList<T>()
    for (item in this)
        if (yielding)
            list.add(item)
        else if (!predicate(item)) {
            list.add(item)
            yielding = true
        }
    return list
}

去除滿足條件的元素诸迟,當(dāng)遇到一個(gè)不滿足條件的元素時(shí),中止操作愕乎,返回剩下的元素子集合阵苇。

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.dropWhile({it%2==0})
[9, 11, 12, 16]

dropLast(n: Int) 從最后去除n個(gè)元素

函數(shù)定義:

public fun <T> List<T>.dropLast(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    return take((size - n).coerceAtLeast(0))
}

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.dropLast(3)
[2, 4, 6, 8, 9]
>>> list.dropLast(100)
[]
>>> list.dropLast(0)
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.dropLast(-1)
java.lang.IllegalArgumentException: Requested element count -1 is less than zero.
    at kotlin.collections.CollectionsKt___CollectionsKt.dropLast(_Collections.kt:573)

dropLastWhile(predicate: (T) -> Boolean) 從最后滿足條件的元素

函數(shù)定義:

public inline fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T> {
    if (!isEmpty()) {
        val iterator = listIterator(size)
        while (iterator.hasPrevious()) {
            if (!predicate(iterator.previous())) {
                return take(iterator.nextIndex() + 1)
            }
        }
    }
    return emptyList()
}

代碼示例:

>>> val list = listOf(2,4,6,8,9,11,12,16)
>>> list.dropLastWhile({it%2==0})
[2, 4, 6, 8, 9, 11]

slice(indices: IntRange) 取開始下標(biāo)至結(jié)束下標(biāo)元素子集合

函數(shù)定義:

public fun <T> List<T>.slice(indices: IntRange): List<T> {
    if (indices.isEmpty()) return listOf()
    return this.subList(indices.start, indices.endInclusive + 1).toList()
}

代碼示例:

val list = listOf(2,4,6,8,9,11,12,16)
>>> list
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.slice(1..3)
[4, 6, 8]
>>> list.slice(2..7)
[6, 8, 9, 11, 12, 16]
>>> list
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.slice(1..3)
[4, 6, 8]
>>> list.slice(2..7)
[6, 8, 9, 11, 12, 16]

slice(indices: Iterable<Int>)返回指定下標(biāo)的元素子集合

函數(shù)定義:

public fun <T> List<T>.slice(indices: Iterable<Int>): List<T> {
    val size = indices.collectionSizeOrDefault(10)
    if (size == 0) return emptyList()
    val list = ArrayList<T>(size)
    for (index in indices) {
        list.add(get(index))
    }
    return list
}

這個(gè)函數(shù)從簽名上看,不是那么簡單直接感论。從函數(shù)的定義看绅项,這里的indices是當(dāng)做原來集合的下標(biāo)來使用的。

代碼示例:

>>> list
[2, 4, 6, 8, 9, 11, 12, 16]
>>> list.slice(listOf(2,4,6))
[6, 9, 12]

我們可以看出比肄,這里是取出下標(biāo)為2快耿,4,6的元素芳绩。而不是直觀理解上的掀亥,去掉元素2,4妥色,6搪花。

filterTo(destination: C, predicate: (T) -> Boolean) 過濾出滿足條件的元素并賦值給destination

函數(shù)定義:

public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)
    return destination
}

把滿足過濾條件的元素組成的子集合賦值給入?yún)estination。

代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7)
>>> val dest = mutableListOf<Int>()
>>> list.filterTo(dest,{it>3})
[4, 5, 6, 7]
>>> dest
[4, 5, 6, 7]

filter(predicate: (T) -> Boolean)過濾出滿足條件的元素組成的子集合

函數(shù)定義:

public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}

相對(duì)于filterTo函數(shù),filter函數(shù)更加簡單易用撮竿。從源碼我們可以看出吮便,filter函數(shù)直接調(diào)用的filterTo(ArrayList<T>(), predicate), 其中入?yún)estination被直接默認(rèn)賦值為ArrayList<T>()幢踏。

代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7)
>>> list.filter({it>3})
[4, 5, 6, 7]

另外髓需,還有下面常用的過濾函數(shù):

filterNot(predicate: (T) -> Boolean), 用來過濾所有不滿足條件的元素 ;
filterNotNull() 過濾掉null元素惑折。

5.3.7 映射操作符

map(transform: (T) -> R): List<R>

將集合中的元素通過轉(zhuǎn)換函數(shù)transform映射后的結(jié)果授账,存到一個(gè)集合中返回。

>>> val list = listOf(1,2,3,4,5,6,7)
>>> list.map({it})
[1, 2, 3, 4, 5, 6, 7]
>>> list.map({it*it})
[1, 4, 9, 16, 25, 36, 49]
>>> list.map({it+10})
[11, 12, 13, 14, 15, 16, 17]

這個(gè)函數(shù)內(nèi)部調(diào)用的是

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

這里的mapTo函數(shù)定義如下:

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
    for (item in this)
        destination.add(transform(item))
    return destination
}

我們可以看出惨驶,這個(gè)map實(shí)現(xiàn)的原理是循環(huán)遍歷原集合中的元素白热,并把通過transform映射后的結(jié)果放到一個(gè)新的destination集合中,并返回destination粗卜。

mapIndexed(transform: (kotlin.Int, T) -> R)

轉(zhuǎn)換函數(shù)transform中帶有下標(biāo)參數(shù)屋确。也就是說我們可以同時(shí)使用下標(biāo)和元素的值來進(jìn)行轉(zhuǎn)換。 其中续扔,第一個(gè)參數(shù)是Int類型的下標(biāo)攻臀。

代碼示例:

>>> val list = listOf(1,2,3,4,5,6,7)
>>> list.mapIndexed({index,it -> index*it})
[0, 2, 6, 12, 20, 30, 42]

mapNotNull(transform: (T) -> R?)

遍歷集合每個(gè)元素,得到通過函數(shù)算子transform映射之后的值纱昧,剔除掉這些值中的null刨啸,返回一個(gè)無null元素的集合。

代碼示例:

>>> val list = listOf("a","b",null,"x",null,"z")
>>> list.mapNotNull({it})
[a, b, x, z]

這個(gè)函數(shù)內(nèi)部實(shí)現(xiàn)是調(diào)用的mapNotNullTo函數(shù):

public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapNotNullTo(destination: C, transform: (T) -> R?): C {
    forEach { element -> transform(element)?.let { destination.add(it) } }
    return destination
}

flatMap(transform: (T) -> Iterable<R>): List<R>

在原始集合的每個(gè)元素上調(diào)用transform轉(zhuǎn)換函數(shù)识脆,得到的映射結(jié)果組成的單個(gè)列表设联。為了更簡單的理解這個(gè)函數(shù),我們跟map(transform: (T) -> R): List<R>對(duì)比下灼捂。

首先看函數(shù)的各自的實(shí)現(xiàn):

map:

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
    for (item in this)
        destination.add(transform(item))
    return destination
}

flatMap:

public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
    return flatMapTo(ArrayList<R>(), transform)
}

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
    for (element in this) {
        val list = transform(element)
        destination.addAll(list)
    }
    return destination
}

我們可以看出离例,這兩個(gè)函數(shù)主要區(qū)別在transform函數(shù)返回上。

代碼示例

>>> val list = listOf("a","b","c")
>>> list.map({it->listOf(it+1,it+2,it+3)})
[[a1, a2, a3], [b1, b2, b3], [c1, c2, c3]]
>>> list.flatMap({it->listOf(it+1,it+2,it+3)})
[a1, a2, a3, b1, b2, b3, c1, c2, c3]

從代碼運(yùn)行結(jié)果我們可以看出悉稠,使用 map 是把list中的每一個(gè)元素都映射成一個(gè)List-n宫蛆,然后以這些List-n為元素,組成一個(gè)大的嵌套的List返回的猛。而使用flatMap則是把list中的第一個(gè)元素映射成一個(gè)List1耀盗,然后把第二個(gè)元素映射成的List2跟List1合并:List1.addAll(List2),以此類推卦尊。最終返回一個(gè)“扁平的”(flat)List叛拷。

其實(shí),這個(gè)flatMap的過程是 map + flatten兩個(gè)操作的組合猫牡。這個(gè)flatten函數(shù)定義如下:

public fun <T> Iterable<Iterable<T>>.flatten(): List<T> {
    val result = ArrayList<T>()
    for (element in this) {
        result.addAll(element)
    }
    return result
}

代碼示例:

>>> val list = listOf("a","b","c")
>>> list.map({it->listOf(it+1,it+2,it+3)})
[[a1, a2, a3], [b1, b2, b3], [c1, c2, c3]]
>>> list.map({it->listOf(it+1,it+2,it+3)}).flatten()
[a1, a2, a3, b1, b2, b3, c1, c2, c3]

5.3.8 分組操作符

groupBy(keySelector: (T) -> K): Map<K, List<T>>

將集合中的元素按照條件選擇器keySelector(是一個(gè)函數(shù))分組胡诗,并返回Map邓线。
代碼示例:

>>> val words = listOf("a", "abc", "ab", "def", "abcd")
>>> val lengthGroup = words.groupBy { it.length }
>>> lengthGroup
{1=[a], 3=[abc, def], 2=[ab], 4=[abcd]}

groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)

分組函數(shù)還有一個(gè)是groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)淌友,根據(jù)條件選擇器keySelector和轉(zhuǎn)換函數(shù)valueTransform分組煌恢。

代碼示例

>>> val programmer = listOf("K&R" to "C", "Bjar" to "C++", "Linus" to "C", "James" to "Java")
>>> programmer
[(K&R, C), (Bjar, C++), (Linus, C), (James, Java)]
>>> programmer.groupBy({it.second}, {it.first})
{C=[K&R, Linus], C++=[Bjar], Java=[James]}


這里涉及到一個(gè) 二元組Pair 類,該類是Kotlin提供的用來處理二元數(shù)據(jù)組的震庭。 可以理解成Map中的一個(gè)鍵值對(duì)瑰抵,比如Pair(“key”,”value”) 等價(jià)于 “key” to “value”。

我們?cè)偻ㄟ^下面的代碼示例器联,來看一下這兩個(gè)分組的區(qū)別:

>>> val words = listOf("a", "abc", "ab", "def", "abcd")
>>> words.groupBy( { it.length })
{1=[a], 3=[abc, def], 2=[ab], 4=[abcd]}
>>> words.groupBy( { it.length },{it.contains("b")})
{1=[false], 3=[true, false], 2=[true], 4=[true]}

我們可以看出二汛,后者是在前者的基礎(chǔ)上又映射了一次{it.contains("b")},把第2次映射的結(jié)果放到返回的Map中了拨拓。

groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>

另外肴颊,我們還可以使用groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>函數(shù)來創(chuàng)建一個(gè)Grouping,然后調(diào)用計(jì)數(shù)函數(shù)eachCount統(tǒng)計(jì)分組:

代碼示例

>>> val words = "one two three four five six seven eight nine ten".split(' ')
>>> words.groupingBy({it.first()}).eachCount()
{o=1, t=3, f=2, s=2, e=1, n=1}

上面的例子是統(tǒng)計(jì)words列表的元素單詞中首字母出現(xiàn)的頻數(shù)渣磷。

其中婿着,eachCount函數(shù)定義如下:

@SinceKotlin("1.1")
@JvmVersion
public fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int> =
        // fold(0) { acc, e -> acc + 1 } optimized for boxing
        foldTo( destination = mutableMapOf(),
                initialValueSelector = { _, _ -> kotlin.jvm.internal.Ref.IntRef() },
                operation = { _, acc, _ -> acc.apply { element += 1 } })
        .mapValuesInPlace { it.value.element }

5.3.9 排序操作符

reversed(): List<T>

倒序排列集合元素。
代碼示例

>>> val list = listOf(1,2,3)
>>> list.reversed()
[3, 2, 1]

這個(gè)函數(shù)醋界,Kotlin是直接調(diào)用的java.util.Collections.reverse()方法竟宋。其相關(guān)代碼如下:

public fun <T> Iterable<T>.reversed(): List<T> {
    if (this is Collection && size <= 1) return toList()
    val list = toMutableList()
    list.reverse()
    return list
}

public fun <T> MutableList<T>.reverse(): Unit {
    java.util.Collections.reverse(this)
}


sortedsortedDescending

升序排序和降序排序。

代碼示例

>>> val list = listOf(1,3,2)
>>> list.sorted()
[1, 2, 3]
>>> list.sortedDescending()
[3, 2, 1]

sortedBysortedByDescending

可變集合MutableList的排序操作形纺。根據(jù)函數(shù)映射的結(jié)果進(jìn)行升序排序和降序排序丘侠。
這兩個(gè)函數(shù)定義如下:

public inline fun <T, R : Comparable<R>> MutableList<T>.sortBy(crossinline selector: (T) -> R?): Unit {
    if (size > 1) sortWith(compareBy(selector))
}
public inline fun <T, R : Comparable<R>> MutableList<T>.sortByDescending(crossinline selector: (T) -> R?): Unit {
    if (size > 1) sortWith(compareByDescending(selector))
}

代碼示例

>>> val mlist = mutableListOf("abc","c","bn","opqde","")
>>> mlist.sortBy({it.length})
>>> mlist
[, c, bn, abc, opqde]
>>> mlist.sortByDescending({it.length})
>>> mlist
[opqde, abc, bn, c, ]

5.3.10 生產(chǎn)操作符

zip(other: Iterable<R>): List<Pair<T, R>>

兩個(gè)集合按照下標(biāo)配對(duì),組合成的每個(gè)Pair作為新的List集合中的元素逐样,并返回蜗字。

如果兩個(gè)集合長度不一樣,取短的長度官研。

代碼示例

>>> val list1 = listOf(1,2,3)
>>> val list2 = listOf(4,5,6,7)
>>> val list3 = listOf("x","y","z")
>>> list1.zip(list3)
[(1, x), (2, y), (3, z)]
>>> list3.zip(list1)
[(x, 1), (y, 2), (z, 3)]
>>> list2.zip(list3)
[(4, x), (5, y), (6, z)]  // 取短的長度
>>> list3.zip(list2)
[(x, 4), (y, 5), (z, 6)]
>>> list1.zip(listOf<Int>())
[]

這個(gè)zip函數(shù)的定義如下:

public infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>> {
    return zip(other) { t1, t2 -> t1 to t2 }
}

我們可以看出秽澳,其內(nèi)部是調(diào)用了zip(other) { t1, t2 -> t1 to t2 }。這個(gè)函數(shù)定義如下:

public inline fun <T, R, V> Iterable<T>.zip(other: Iterable<R>, transform: (a: T, b: R) -> V): List<V> {
    val first = iterator()
    val second = other.iterator()
    val list = ArrayList<V>(minOf(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10)))
    while (first.hasNext() && second.hasNext()) {
        list.add(transform(first.next(), second.next()))
    }
    return list
}

依次取兩個(gè)集合相同索引的元素戏羽,使用提供的轉(zhuǎn)換函數(shù)transform得到映射之后的值担神,作為元素組成一個(gè)新的List,并返回該List始花。列表的長度取兩個(gè)集合中最短的妄讯。

代碼示例

>>> val list1 = listOf(1,2,3)
>>> val list2 = listOf(4,5,6,7)
>>> val list3 = listOf("x","y","z")
>>> list1.zip(list3, {t1,t2 -> t2+t1})
[x1, y2, z3]
>>> list1.zip(list2, {t1,t2 -> t1*t2})
[4, 10, 18]

unzip(): Pair<List<T>, List<R>>

首先這個(gè)函數(shù)作用在元素是Pair的集合類上。依次取各個(gè)Pair元素的first, second值酷宵,分別放到List<T>亥贸、List<R>中,然后返回一個(gè)first為List<T>浇垦,second為List<R>的大的Pair炕置。

函數(shù)定義

public fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>> {
    val expectedSize = collectionSizeOrDefault(10)
    val listT = ArrayList<T>(expectedSize)
    val listR = ArrayList<R>(expectedSize)
    for (pair in this) {
        listT.add(pair.first)
        listR.add(pair.second)
    }
    return listT to listR
}

看到這里,仍然有點(diǎn)抽象,我們直接看代碼示例:

>>> val listPair = listOf(Pair(1,2),Pair(3,4),Pair(5,6))
>>> listPair
[(1, 2), (3, 4), (5, 6)]
>>> listPair.unzip()
([1, 3, 5], [2, 4, 6])

partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>>

根據(jù)判斷條件是否成立朴摊,將集合拆分成兩個(gè)子集合組成的 Pair默垄。我們可以直接看函數(shù)的定義來更加清晰的理解這個(gè)函數(shù)的功能:

public inline fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> {
    val first = ArrayList<T>()
    val second = ArrayList<T>()
    for (element in this) {
        if (predicate(element)) {
            first.add(element)
        } else {
            second.add(element)
        }
    }
    return Pair(first, second)
}

我們可以看出,這是一個(gè)內(nèi)聯(lián)函數(shù)甚纲。

代碼示例

>>> val list = listOf(1,2,3,4,5,6,7,8,9)
>>> list
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list.partition({it>5})
([6, 7, 8, 9], [1, 2, 3, 4, 5])

plus(elements: Iterable<T>): List<T>

合并兩個(gè)List口锭。

函數(shù)定義

public operator fun <T> Iterable<T>.plus(elements: Iterable<T>): List<T> {
    if (this is Collection) return this.plus(elements)
    val result = ArrayList<T>()
    result.addAll(this)
    result.addAll(elements)
    return result
}

我們可以看出,這是一個(gè)操作符函數(shù)介杆【椴伲可以用”+”替代 。

代碼示例

>>> val list1 = listOf(1,2,3)
>>> val list2 = listOf(4,5)
>>> list1.plus(list2)
[1, 2, 3, 4, 5]
>>> list1+list2
[1, 2, 3, 4, 5]

關(guān)于plus函數(shù)還有以下的重載函數(shù):

plus(element: T): List<T>
plus(elements: Array<out T>): List<T>
plus(elements: Sequence<T>): List<T>

等春哨。

plusElement(element: T): List<T>

在集合中添加一個(gè)元素荆隘。
函數(shù)定義

@kotlin.internal.InlineOnly
public inline fun <T> Iterable<T>.plusElement(element: T): List<T> {
    return plus(element)
}

我們可以看出,這個(gè)函數(shù)內(nèi)部是直接調(diào)用的plus(element: T): List<T>赴背。

代碼示例

>>> list1 + 10
[1, 2, 3, 10]
>>> list1.plusElement(10)
[1, 2, 3, 10]
>>> list1.plus(10)
[1, 2, 3, 10]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末臭胜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子癞尚,更是在濱河造成了極大的恐慌耸三,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇揩,死亡現(xiàn)場(chǎng)離奇詭異仪壮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胳徽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門积锅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人养盗,你說我怎么就攤上這事缚陷。” “怎么了往核?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵箫爷,是天一觀的道長。 經(jīng)常有香客問我聂儒,道長虎锚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任衩婚,我火速辦了婚禮窜护,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘非春。我一直安慰自己柱徙,他們只是感情好缓屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著护侮,像睡著了一般藏研。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上概行,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音弧岳,去河邊找鬼凳忙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛禽炬,可吹牛的內(nèi)容都是我干的涧卵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼腹尖,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼柳恐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起热幔,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤乐设,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后绎巨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體近尚,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年场勤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戈锻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡和媳,死狀恐怖格遭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情留瞳,我是刑警寧澤拒迅,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站她倘,受9級(jí)特大地震影響坪它,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帝牡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一往毡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧靶溜,春花似錦开瞭、人聲如沸懒震。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽个扰。三九已至,卻和暖如春葱色,著一層夾襖步出監(jiān)牢的瞬間递宅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國打工苍狰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留办龄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓淋昭,卻偏偏與公主長得像俐填,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翔忽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容