
在Kotlin中,如果您创建List或Map ,则它是只读的( 类似于Immutable,但略有不同 )。 这意味着,一旦构造了集合,便没有添加或放置或删除功能要添加到集合中或从集合中删除的功能。
注意:如果您仍然希望有一个可变集合,则需要声明一个MutableList或MutableMap 。 我的建议是仅在您确实需要可变的临时列表时才这样做。
如何创建只读集合
在Java中,要创建一个List,通常如下所示
List<String> countries = new ArrayList(); countries.add("Australia"); countries.add("Korea"); countries.add("Malaysia");
但是我们不能再在Kotlin中做同样的事情,因为创建列表后就无法将其添加到列表中。
因此,您可以使用Kotlin的CollectionKt类提供的listOf函数。
val countries = listOf ("Australia", "Korea", "Malaysia")
同样对于Map,您可以使用mapOf函数,如下所示。
val mapCountryCapital = mapOf ( Pair("Australia", "Canberra"), Pair("Malaysia", "Putrajaya"))
筛选集合
假设您有以下列表
class Country(val country: String, val continent: String)
val countries = listOf(Country("Korea", "Asia") , Country("Malaysia", "Asia"), Country("Romania", "Europe"), Country("Somalia", "Africa"))
而且,您只希望筛选并保留亚洲国家/地区在新列表中。 您不能使用添加或删除 。 因此,您不能在过程中使用for循环。
这样,您必须进行搜索以了解如何实现这一目标。 如下所示。
val asiaCountries = countries. filter { it.continent == "Asia" }
将元素提取到另一个列表中
假设您有以下列表
class Country(val country: String, val capital: String)
val countries = listOf(Country("Australia", "Canberra"), Country("Malaysia", "Putrajaya"), Country("Romania", "Bucharest"))
现在,您只想创建一个首都列表。 同样,遍历列表以从列表的每个项目中提取元素也没有意义,因为您不能使用add更改列表。
您必须搜索这是怎么可能的。 如下所示。
val capitals = countries. map { it.capital }
将列表中的列表展平到新列表
假设您有以下列表
class Country(val country: String, val cities: List<String>)
val countries = listOf( Country("Australia", listOf("Canberra", "Melbourne")), Country("Malaysia", listOf("Putrajaya", "Penang")))
现在,您需要提供的国家/地区的城市清单。 快速操作如下,但这是不正确的,因为这会将城市列表存储在新列表中。
val capitals = countries.map{ it.cities } // Wrong answer
那你怎么办呢? 同样,没有循环遍历列表并对其进行操作。 因此,您必须搜索执行此操作的好方法。 好消息是,它很简单,如下所示。
val cities = countries. flatmap { it.cities }
将列表转换为地图
假设您有以下列表
class Country(val country: String, val capital: String)
val countries = listOf(Country("Australia", "Canberra"), Country("Brazil", "Brasilia"), Country("Malaysia", "Putrajaya"))
搜索将很困难。 您想要一张地图,这样就可以通过给一个国家轻松找到首都。
同样,默认情况下,地图是只读的。 这样就无法创建地图并将其放置到地图上。 由于这一挑战,您必须搜索如何完成它。 幸运的是,它也如下所示
val mapCountryCaptial = countries.associateBy({ it.country }, { it.capital })
构造新列表时过滤空项目
假设您有以下代码
val cities = listOf("Xian", "Medan", "Putrajaya", "Canberra")
val mapCapitalCountry= mapOf( Pair("Brasilia", "Brazil"), Pair("Canberra", "Australia"), Pair("Putrajaya", "Malaysia"))
您想要列出在城市列表中注明首都的国家/地区。 第一个想法很简单,只需使用map。
// Incorrect val countriesOfListedCapital = cities. map { mapCapitalCountry[it] }
但是,这将导致列表大小为4,其中包含2个空值,因为Xian和Medan将根据mapCapitalCountry [it]生成空值。
要进行改进,您可以先过滤掉null并进行映射。
// Partially correct. val countriesOfListedCapital = cities.filter { mapCapitalCountry[it] != null } .map { mapCapitalCountry[it] }
现在得到2个项目的结果,即澳大利亚和马来西亚。 但是,如果您详细检查,countriesOfListedCapital的类型为List <String ? >。 这是一个可为null的类型,不理想。
再想一想,也许我们可以通过使用Elvis Operator将其强制为非空,返回空String而不是null; 即使您知道这不会发生,因为所有null都已被过滤掉。
// Almost correct val countriesOfListedCapital = cities.filter { mapCapitalCountry[it] != null } .map { mapCapitalCountry[it] ?: "" }
现在好了。 countryOfListedCapital是nowList <String>。 但是,这仍然不是理想的,因为您必须显式添加Elvis运算符,因为您知道什么也不做。
好吧,好消息是,还有一个收集功能可以实现此目的,而没有上述任何复杂性。
val countriesOfListedCapital = cities. mapNotNull { mapCapitalCountry[it] }
好吧,由于Kotlin列表和“地图只读”集合的限制,它迫使我寻找正确的方法来执行此操作,从而使代码非常简洁。
Kotlin集合提供了许多非常有用的操作。 上面列出的只是其中很少一部分。 还有更多值得探索的地方。 玩得开心看看!
如果您喜欢我的帖子并想获取将来的更新,请单击👏👏👏,在medium 上关注我, Twitter 要么 脸书
From: https://hackernoon.com/read-only-collection-in-kotlin-leads-to-better-coding-40cdfa4c6359