知识点
通过本篇文章,你可以学到
- flatMap 扩展函数的使用
- distinctBy 扩展函数的使用
- 加减操作符的使用
缘起
首先,我们看看用到的实体类的结构:
Person 接口
interface Person {
val id: Int
val name: String
}
Student 数据类
data class Student(override val id: Int, override val name: String) : Person
Teacher 数据类
data class Teacher(override val id: Int, override val name: String, val studentList: List<Student>) : Person
我们可以看到,Teacher
类和 Student
类都同时实现了 Person
接口,然后 Teacher
类还多了一个 studentList 属性。
简单来说,老师和学生都是人类,然后每个老师可能会管理多个学生。
那么,如果我们想要知道一共有多少人,以及每个人的 id 和姓名,我们可以怎么做呢?
数据源
原始数据如下:
[
{
"id":1234,
"name":"张老师",
"studentList":[
{
"id":2234,
"name":"王麻子"
},
{
"id":2235,
"name":"狗蛋"
}
]
},
{
"id":1235,
"name":"李老师",
"studentList":[
{
"id":2236,
"name":"赵雪梅"
},
{
"id":2237,
"name":"马冬梅"
}
]
},
{
"id":1236,
"name":"王老师",
"studentList":[
{
"id":2237,
"name":"李华"
},
{
"id":2238,
"name":"胖虎"
}
]
}
]
代码实现
首先,我们将以上的 json 数据反序列化成 List<Teacher>
。
val teacherList = gson.fromJson<List<Teacher>>(json, object : TypeToken<List<Teacher>>() {}.type)
然后,我们就可以使用 Kotlin 给我们提供的 flatMap
扩展函数方便的转换成 List<Person>
这样的数据结构了。
val personList = teacherList.flatMap { listOf(it) + it.studentList }
Tips:这里我们使用了 Kotlin 中的加减操作符重载 ,实现了 List + List 这样的效果。源码如下:
/**
* Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
*/
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
if (elements is Collection) {
val result = ArrayList<T>(this.size + elements.size)
result.addAll(this)
result.addAll(elements)
return result
} else {
val result = ArrayList<T>(this)
result.addAll(elements)
return result
}
}
拿到了 personList 之后,我们就可以调用 personList.size
获取到总人数了,遍历 personList 集合我们就能拿到每个人的 id 和 姓名信息了。
到这里,我们的需求似乎就已经解决了(只是使用了一个 flatMap 操作符?Kotlin 的语法糖也太甜了吧!)
代码优化
可是,实际情况是同一个学生可能被多位老师所管理,那么这样拿到的数据就可能会有冗余。
这个时候我们可以通过 id 对集合再去个重嘛~
val personList = teacherList.flatMap { listOf(it) + it.studentList }.distinctBy { it.id }
Tips:这里我们使用 Kotlin 给我们提供的 distinctBy
扩展函数,通过 id 进行去重处理。源码如下:
/**
* Returns a list containing only elements from the given collection
* having distinct keys returned by the given [selector] function.
*
* Among elements of the given collection with equal keys, only the first one will be present in the resulting list.
* The elements in the resulting list are in the same order as they were in the source collection.
*
* @sample samples.collections.Collections.Transformations.distinctAndDistinctBy
*/
public inline fun <T, K> Iterable<T>.distinctBy(selector: (T) -> K): List<T> {
val set = HashSet<K>()
val list = ArrayList<T>()
for (e in this) {
val key = selector(e)
if (set.add(key))
list.add(e)
}
return list
}
如果对你有帮助的话,欢迎一键三连+关注哦~
本文由
A lonely cat
原创发布于
阳光沙滩
,未经作者授权,禁止转载