[Android]Kotlin的集合函数

前言

如果您正在阅读此博客,那么我们很确定您已经完全转向 Kotlin 进行 Android 开发,或者您计划很快转向 Kotlin。在任何情况下,此博客都非常适合您。所以,让我们进入正题。

在我们的 Android 应用程序中,我们处理各种集合,例如列表、地图、集合等。我们对这些执行了许多操作,但是您是否知道有许多 Kotlin 集合函数可以让我们的生活更轻松。如果您想对任何集合执行一些操作(简单或复杂),那么很有可能必须有一些集合功能可以使您的整个 Android App 开发变得更简单和容易。

在本博客中,我们将了解其中的许多 Kotlin 集合函数。您可以将此博客添加为书签,并将此博客作为 Kotlin 集合函数的备忘单。所以,让我们从一个简单的操作开始,即从数组中删除重复的字符串。

删除重复的字符串

有很多方法可以从数组中删除重复的字符串:

// Maintain the original order of items
val devs = arrayOf("Amit", "Ali", "Amit", "Sumit", "Sumit", "Himanshu")
print(devs.distinct()) // [Amit, Ali, Sumit, Himanshu]

// Maintain the original order of items
val devs = arrayOf("Amit", "Ali", "Amit", "Sumit", "Sumit", "Himanshu")
print(devs.toSet()) // [Amit, Ali, Sumit, Himanshu]

// Maintain the original order of items
val devs = arrayOf("Amit", "Ali", "Amit", "Sumit", "Sumit", "Himanshu")
print(devs.toMutableSet()) // [Amit, Ali, Sumit, Himanshu]

// DO NOT Maintain the original order of items
val devs = arrayOf("Amit", "Ali", "Amit", "Sumit", "Sumit", "Himanshu")
print(devs.toHashSet()) // [Amit, Ali, Sumit, Himanshu]

将数组或列表转换为字符串

您可以使用 将数组或列表转换为字符串joinToString。例如,如果您有一个城市列表(德里、孟买、班加罗尔),那么您可以将该列表转换为一个字符串,例如“印度是最佳旅游国家之一。您可以访问德里、孟买、班加罗尔等,享受你的假期”。在这里,德里、孟买、班加罗尔是您拥有的清单项目。

val someKotlinCollectionFunctions = listOf(
    "distinct", "map",
    "isEmpty", "contains",
    "filter", "first",
    "last", "reduce",
    "single", "joinToString"
)

val message = someKotlinCollectionFunctions.joinToString(
    separator = ", ",
    prefix = "Kotlin has many collection functions like: ",
    postfix = "and they are awesome.",
    limit = 3,
    truncated = "etc "
)

print(message) // Kotlin has many collection functions like: distinct, map, isEmpty, etc and they are awesome.

将集合转换为单个结果

如果要将给定的集合转换为单个结果,则可以使用reducefunction. 例如,您可以找到列表中所有元素的总和:

val numList = listOf(1, 2, 3, 4, 5)
val result = numList.reduce { result, item ->
    result + item
}
print(result) // 15

// NOTE: If the list is empty, then it will throw a RuntimeException

查找是否所有元素都满足特定条件

如果您有一个数据元素的数组或列表,并且想要查找是否所有元素都满足特定条件,那么您可以all在 Kotlin 中使用。

data class User(val id: Int, val name: String, val isCricketLover: Boolean, val isFootballLover: Boolean)

val user1 = User(id = 1, name = "Amit", isCricketLover = true, isFootballLover = true)
val user2 = User(id = 2, name = "Ali", isCricketLover = true, isFootballLover = true)
val user3 = User(id = 3, name = "Sumit", isCricketLover = true, isFootballLover = false)
val user4 = User(id = 4, name = "Himanshu", isCricketLover = true, isFootballLover = false)

val users = arrayOf(user1, user2, user3, user4)

val allLoveCricket = users.all { it.isCricketLover }
print(allLoveCricket) // true

val allLoveFootball = users.all { it.isFootballLover }
print(allLoveFootball) // false

根据特定条件查找特定元素

您可以通过在 Kotlin 中使用findand从满足特定条件的元素列表中找到特定元素。single例如,在学生列表中,您可以找到卷号为 5 的学生。

find返回匹配给定条件的第一个元素,如果没有找到这样的元素,则返回 null 。

Whilesingle返回匹配给定条件的单个元素,或者如果列表中有多个匹配元素或没有匹配元素,则会抛出异常。

data class User(val id: Int, val name: String)

val users = arrayOf(
    User(1, "Amit"),
    User(2, "Ali"),
    User(3, "Sumit"),
    User(4, "Himanshu")
)

val userWithId3 = users.single { it.id == 3 }
print(userWithId3) // User(id=3, name=Sumit)

val userWithId1 = users.find { it.id == 1 }
print(userWithId1) // User(id=1, name=Amit)

将您的列表分成多个较小的子列表

在很多情况下,您有一个较大的列表,并且您希望将其划分为较小的部分,然后对这些子列表执行一些操作。因此,使用该chunked功能可以轻松实现这一点。

val numList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val chunkedLists = numList.chunked(3)
print(chunkedLists) // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

制作数组的副本

您可以使用各种功能复制现有数组,例如:

  • copyInto:这会将一个数组的元素替换为另一个数组,或者如果目标数组由于大小限制或索引超出范围而无法保存原始数组的元素,则会引发异常。
val arrayOne = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val arrayTwo = arrayOf(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
arrayOne.copyInto(destination = arrayTwo, destinationOffset = 2, startIndex = 0, endIndex = 4)
arrayTwo.forEach {print("$it ")} // 11 12 1 2 3 4 17 18 19 20

同样,还有其他函数可用于复制数组的元素。例如:

  • copyOfRange(fromIndex, toIndex):返回一个新数组,它是原始数组指定范围的副本。

  • copyOf()copyOf(newSize):返回一个新数组,它是原始数组的副本,调整为给定的 newSize,或者如果未传递 newSize,则将复制整个数组。

将集合类型更改为其他

根据情况,您可以更改集合的类型。在这里,您可以通过创建新集合或引用旧集合来将一个集合的类型更改为另一种类型。例如:

toIntArraytoBooleanArraytoLongArraytoShortArraytoByteArraytoDoubleArraytoListtoMaptoSettoPair等可用于将一个集合的类型更改为另一种类型。

var uIntArray = UIntArray(5) { 1U }
var intArray = uIntArray.toIntArray()
intArray[0] = 0
print(uIntArray.toList()) // [1, 1, 1, 1, 1]
print(intArray.toList()) // [0, 1, 1, 1, 1]

在这里,我们正在制作一个新集合,新集合中的更改不会反映在旧集合中。但是,与此同时,您可以通过保留对旧集合的引用来更改集合的类型,即一个集合中的更改将自动反映在另一个集合中。为此to,我们需要使用as. 例如:

asIntArrayasLongArrayasShortArrayasByteArrayasList等。

var uIntArray = UIntArray(5) { 1U }
var intArray = uIntArray.asIntArray()
intArray[0] = 0
print(uIntArray.toList()) // [0, 1, 1, 1, 1]
print(intArray.toList()) // [0, 1, 1, 1, 1]

使用某个键关联数据

使用某个键关联数据

如果您有一个数据列表,并且希望借助数据元素中存在的某些键来关联数据,那么您可以使用associateBy.

data class Contact(val name: String, val phoneNumber: String)

val contactList = listOf(
    Contact("Amit", "+9199XXXX1111"),
    Contact("Ali", "+9199XXXX2222"),
    Contact("Himanshu", "+9199XXXX3333"),
    Contact("Sumit", "+9199XXXX4444")
)

val phoneNumberToContactMap = contactList.associateBy { it.phoneNumber }
print(phoneNumberToContactMap)
// Map with key: phoneNumber and value: Contact
// {
//     +9199XXXX1111=Contact(name=Amit, phoneNumber=+9199XXXX1111),
//     +9199XXXX2222=Contact(name=Ali, phoneNumber=+9199XXXX2222),
//     +9199XXXX3333=Contact(name=Himanshu, phoneNumber=+9199XXXX3333),
//     +9199XXXX4444=Contact(name=Sumit, phoneNumber=+9199XXXX4444)
// }

在上面的例子中,key 是 phoneNumber,value 是 Contact。如果您不想将整个 Contact 作为值,那么您可以像这样简单地传递所需的值:

val phoneNumberToContactMap = contactList.associateBy({it.phoneNumber}, {it.name})
print(phoneNumberToContactMap)
// Map with key: phoneNumber and value: name
// {
//     +9199XXXX1111=Amit, 
//     +9199XXXX2222=Ali, 
//     +9199XXXX3333=Himanshu, 
//     +9199XXXX4444=Sumit}
// }

在集合中查找不同的元素

我们可以使用 distinct 函数来获取集合中唯一元素的列表。

val list = listOf(1, 2, 2, 3, 3, 3, 4, 4, 4, 4)
println(list.distinct()) // [1, 2, 3, 4]

收藏联盟

您可以使用该union函数获取两个集合的唯一元素。两个集合的元素顺序将被保留,但第二个集合的元素将添加在第一个集合的元素之后。

val listOne = listOf(1, 2, 3, 3, 4, 5, 6)
val listTwo = listOf(2, 2, 4, 5, 6, 7, 8)
println(listOne.union(listTwo)) // [1, 2, 3, 4, 5, 6, 7, 8]

集合的交集

要获取两个集合中共有的元素,您可以使用intersect返回包含两个集合的公共元素的集合的函数。

val listOne = listOf(1, 2, 3, 3, 4, 5, 6)
val listTwo = listOf(2, 2, 4, 5, 6, 7, 8)
println(listOne.intersect(listTwo)) // [2, 4, 5, 6]

只保留指定的元素

如果在集合中,您只想保留指定的元素,那么您可以使用retainAll函数。由于此函数会修改您的列表,因此请确保您的列表或数组是可变的。

retainAll如果从集合中删除任何元素,则返回 true,否则返回 false。

val listOne = mutableListOf(1, 2, 3, 3, 4, 5, 6)
val listTwo = listOf(1, 2, 3, 3, 4, 5, 6)
val listThree = listOf(1, 2, 3, 3, 4, 5, 7)
println(listOne.retainAll(listTwo)) // false
println(listOne.retainAll(listThree)) // true
println(listOne) // [1, 2, 3, 3, 4, 5]

同样,您可以使用removeAll删除一个集合中存在于另一个集合中的所有元素。

根据某些条件过滤集合

您可以filter使用过滤器根据特定条件进行集合。这将返回一个列表,其中包含满足给定条件的元素。

val list = listOf(1, 2, 3, 4, 5, 6, 7, 8)
val filteredList = list.filter { it % 2 == 0 }
print(filteredList) // [2, 4, 6, 8]

同样,您可以使用 . 根据元素的索引过滤集合filterIndexed

如果要将过滤后的元素存储在某个集合中,则可以使用filterIndexedTo

val list = listOf(1, 2, 3, 4, 5, 6, 7, 8)
val filteredList = mutableListOf<Int>()
list.filterIndexedTo(filteredList) { index, i -> list[index] % 2 == 0 }
print(filteredList) // [2, 4, 6, 8]

您还可以使用 . 查找集合中指定类型实例的元素filterIsInstance

val mixedList = listOf(1, 2, 3, "one", "two", 4, "three", "four", 5, 6, "five", 7)
val strList = mixedList.filterIsInstance<String>()
print(strList) // [one, two, three, four, five]

邮编系列

zip返回对的列表。该对的第一个元素将从第一个集合中获取,而该对的第二个元素将从第二个集合中获取。返回列表的大小将等于最短集合的大小。

val listOne = listOf(1, 2, 3, 4, 5)
val listTwo = listOf("a", "b", "c", "d", "e", "f")
print(listOne zip listTwo) // [(1, a), (2, b), (3, c), (4, d), (5, e)]

与集合中的下一个一起压缩

zipWithNext返回对的列表。该对的元素将是集合的相邻元素。

val list = listOf(1, 2, 3, 4, 5)
print(list.zipWithNext()) // [(1, 2), (2, 3), (3, 4), (4, 5)]

解压缩集合

unzip返回一对列表。第一个列表由每对的第一个元素组成,第二个列表由每对的第二个元素组成。

val list = listOf("Amit" to 8, "Ali" to 10, "Sumit" to 4, "Himanshu" to 2)
val (players, footballSkills) = list.unzip()
print(players) // [Amit, Ali, Sumit, Himanshu]
print(footballSkills) // [8, 10, 4, 2]

根据某些条件将数组拆分为两部分

如果您想根据某些条件(例如 isFootballFan)将数据拆分为两部分,则可以使用partition.

data class User(val id: Int, val name: String, val isFootballLover: Boolean)

val users = listOf(
    User(1, "Amit", true),
    User(2, "Ali", true),
    User(3, "Sumit", false),
    User(4, "Himanshu", false)
)

val (footballLovers, nonFootballLovers) = users.partition { it.isFootballLover }
print(footballLovers) // [User(id=1, name=Amit, isFootballLover=true), User(id=2, name=Ali, isFootballLover=true)]
print(nonFootballLovers) // [User(id=3, name=Sumit, isFootballLover=false), User(id=4, name=Himanshu, isFootballLover=false)]

反转列表

您可以使用reversedandasReversed函数在 Kotlin 中反转列表。

val list = listOf(1, 2, 3, 4, 5)
print(list.reversed()) // [5, 4, 3, 2, 1]
print(list.asReversed()) // [5, 4, 3, 2, 1]

两者都提供相同的输出,但这些功能不同。

reversed()函数可应用于 Array、List 和 MutableList。它生成一个与原始列表相反的新列表。

但该asReversed()功能可以应用于 List 和 MutableList。它不会生成新列表,因为在反转之后,新元素仍然引用旧元素。因此,其中一个的任何变化都会导致另一个的变化。

同样,还有其他函数可用于反转元素,例如reversedArray(), reverse()

根据某些条件对集合的元素进行分组

您可以使用groupBy()基于特定条件对集合的元素进行分组。例如,下面的代码将根据除以 4 时的余数对列表的元素进行分组,即有 4 个组(当余数 = 0、1、2 和 3 时)

val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(list.groupBy { it % 4 })
// {
//     1=[1, 5, 9], 
//     2=[2, 6, 10], 
//     3=[3, 7], 
//     0=[4, 8]
// }

对集合的元素进行排序

您可以使用该sorted()函数对集合的元素进行排序。这将返回一个排序列表。

val list = listOf(10, 4, 1, 3, 7, 2, 6)
print(list.sorted()) // [1, 2, 3, 4, 6, 7, 10]

同样,还有其他函数可用于根据特定条件对集合进行排序。其中一些函数是sortedArraysortedArrayWithsortedBysortedByDescendingsortedArraydescendingsortedWith等。

因此,这些是在 Kotlin 中处理集合时可以使用的一些集合函数。

作者:Admin MindOrks
链接:https://blog.mindorks.com/kotlin-collection-functions

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

推荐阅读更多精彩内容