65.集合常用操作
2019-10-06 本文已影响0人
写代码的向日葵
1.集合过滤
fun main(args: Array<String>) {
val list1 = listOf<String>("张三", "李四", "王五", "找六", "张四", "李五", "李六")
val list2 = listOf<String>("周芷若", "张无忌", "张五", "李善长", "林青霞", "李寻欢")
//找到第一个集合中第一个姓张的
println(list1.find { it.startsWith("张") })
//把第一个集合中所有姓张的找出来
println(list1.filter { it.startsWith("张") })
//把两个集合中所有姓张的找出来并存放到一个集合中
val mutableList = mutableListOf<String>()
list1.filterTo(mutableList) { it.startsWith("张") }
list2.filterTo(mutableList) { it.startsWith("张") }
println(mutableList)
//把第一个集合中下标为偶数的过滤出来
println(list1.filterIndexed { index, value -> index % 2 == 0 })
}
2.集合排序
fun main(args: Array<String>) {
val list = listOf<String>("a", "b", "e", "f", "c", "g", "d")
//正序
println(list.sorted())
//倒序
println(list.sortedDescending())
val persons = listOf<Person>(Person("林青霞", 50), Person("张曼玉", 30), Person("柳岩", 70))
//排序
val sortedPerson = persons.sortedBy { it.age }
println(sortedPerson)
//倒序
println(persons.sortedByDescending { it.age })
}
data class Person(val name: String, val age: Int)
- sortedBy的实现如下:
image.png 可以看到sortedBy是一个Iterable
的扩展函数,也是一个高阶函数,接收的参数selector
是一个函数类型,然后这个函数的参数是集合类型T
,返回值是泛型R
,R
是一个实现了Comparable
接口的泛型类型,所以上面可以使用it.age
3.分组
fun main(args: Array<String>) {
val list = listOf<String>("张三", "李四", "王五", "找六", "张四", "李五", "李六")
//分组
val map = list.groupBy {
val first = it.substring(0, 1)
when (first) {
"张" -> "张"
"李" -> "李"
else -> "其它"
}
}
}
- 输出结果如下:
image.png
groupBy
源码分析:
a
b
c- 调用顺序为
a->b->c
,通过图a可以看到groupBy
接收一个参数为T
,返回值为K
的函数类型的参数,然后调用图b中的函数,同时给了一个LinkedHashMap<K,MutableList<T>>
作为第一个参数,看到图b的函数实现我们应该就明白了groupBy
这个函数返回值k
的作用了,继续看destination.getOrPut(key) { ArrayList<T>() }
,调用到图c,然后可以看到会从图a传递的LinkedHashMap<K,MutableList<T>>
中通过key
获取一个MutableList<T>
,如果没有获取到,这个时候defaultValue: () -> V
就起作用了,再看这个参数,原来是图b到图c的过程中传递的ArrayList<T>()
,这样就形成了一个整体,根据key获取list,如果有就返回,如果没有则新创建一个,并且添加到LinkedHashMap<K,MutableList<T>>
中,这样groupBy
函数的返回值map
就构建出来了- 图b中剩余的工作就是把遍历出来的元素添加到对应
key
的list
中,最后并且返回图a中构造出来的LinkedHashMap<K,MutableList<T>>
4.最值
fun main(args: Array<String>) {
val list = listOf<String>("a", "c", "b", "v", "f", "g", "e")
//最大值
println(list.max())
//最小值
println(list.min())
val persons = listOf<Person>(Person("林青霞", 50), Person("张曼玉", 30), Person("柳岩", 70))
//最大值
println(persons.maxBy { it.age })
//最小值
println(persons.minBy { it.age })
}
data class Person(val name: String, val age: Int)
- 具体的实现原理,与上面集合排序类似
5.去重复
fun main(args: Array<String>) {
val list = listOf<String>("a", "c", "b", "v", "f", "g", "e", "a", "c")
//去重复
val toSet = list.toSet()
println(toSet)
println(list.distinct())
val persons = listOf<Person>(
Person("林青霞", 50), Person("张曼玉", 30), Person("柳岩", 70), Person("张三", 90),
Person("张三", 20)
)
val distinctBy = persons.distinctBy { it.name.substring(0, 1) }
println(distinctBy)
}
data class Person(val name: String, val age: Int)
- 源码分析
image.png
distinctBy
的参数是一个函数类型,和上面情况一样
- 可以看到去重主要是利用了
HashSet
,而HashSet
主要是对HashMap
做了一层封装,看到只有set.add(key)
为true
的时候,才会将元素添加到集合中,HashSet
的add
函数调用的是HashMap
的put
函数,看到HashMap
的最终实现如下:
a
bHashSet
的add
为true的时候表明return map.put(e, PRESENT)==null
成立,看到b图中,只有添加的元素不存在,为新元素的时候才为true,再倒回去看,这样就去重成功了,平时我们开发的时候,也值得借鉴这种思想。