集合
1.集合的分类
list:是一个有序集合,通过索引来访问集合元素。元素可以在集合中出现多次。
set:集合中的元素是唯一的,一般来说set集合中的元素顺序并不重要。
map:是一组键值对,键是唯一的,每个键刚好映射到一个值,值是可以重复的。
2.集合的类型
kotlin标准库提供了基本集合类型的实现:set、list以及map。分为只读类型和可变类型。
只读类型是“型变“的,可变集合不是“型变”的。map在值(value)类型上是型变的,在键(key)类型上是不型变的。
val list:List<CharSequence> = listOf<String>("hello")
// val mutableList: MutableList<CharSequence> = mutableListOf<String>("hello")//error
val map:Map<CharSequence, CharSequence> = mapOf<CharSequence,String>()//public interface Map<K, out V>
1.Collection
Collection<out E>是集合层次的根。
MutableCollection是具有写操作的Collection接口。
2.List
List<out E>以指定的顺序存储元素,并提供以索引访问元素的方法。List中的元素可以重复。
MutableList<E>是可以进行写操作的List
kotlin中List的默认实现是ArrayList
3.Set
Set<out E>存储唯一的元素,它们的顺序通常是未定义的。null元素也是唯一的,一个Set集合只能包含一个null元素。
MutableSet<E>是带有写操作的Set。
Set的默认实现是LInkedHashSet,保留元素的插入顺序。另一种实现HashSet,不声明元素的顺序。
由于Set的顺序是不确定的,所以它没有提供相应的按索引查找元素的方法。
4.Map
Map<K, out V>不是Collection接口的继承者。
MutableMap<K, V>是具有写操作接口的Map.
Map的默认实现是LInkedHashMap,迭代Map时保留Map的插入顺序。
3.集合构造
1、由元素构造
listOf<T>()、setOf<T>()、mapOf<T>(),mutableListOf<T>()、mutableSetof<T>()、mutableMapOf<T>()。
val set: Set<String> = setOf("hello", "world")
val list = mutableListOf("hello", "world")
val map = mapOf<String, Int>("key1" to 1, "key2" to 2)
2、空集合
emptyList<T>()、emptySet<T>()、emptyMap<T>(),创建的是只读属性的空集合。
val eList = emptyList<String>()
val eSet: Set<String> = emptySet()
val eMap = emptyMap<String, Int>()
3、List的初始化构造函数
List接收大小和初始化函数的构造函数,该初始化函数根据所以定义元素的值。
val list1 = List(3, {
it + 2 })
println(list1)
[2, 3, 4]
4、具体类型的构造函数
val list2 = ArrayList<String>()
val map2 = HashMap<String, Int>()
5、复制
创建与先由集合具有相同元素的集合。
toList()、toMutableList()、toMap()…,进行的是深复制的,创建了一个与原集合具有相同元素的新集合。
val list = mutableListOf("hello", "world")
val list3 = list.toList()
list.add("good")
println(list)
println(list3)
[hello, world, good]
[hello, world]
6、可以使用只读属性的引用接收可变集合的对象,限制其可变性。
val list = mutableListOf("hello", "world")
list.add("good")
val list4: List<String> = list
list.add("hi")
println(list4)
[hello, world, good, hi]
6、调用其他集合函数
如过滤生成新的与过滤器匹配的集合,映射生成转换集合列表,关联生成Map。
val list6 = listOf("hi", "hello", "world", "boy")
val list7 = list6.filter {
it.length < 4 }
println(list6)
println(list7)
val set2 = setOf(1, 2, 3)
val set3 = set2.map {
"value is $it" }
println(set2)
println(set3)
val map3 = list6.associateWith {
it.length }
println(map3)
[hello, world, good, hi]
[hi, hello, world, boy]
[hi, boy]
[1, 2, 3]
[value is 1, value is 2, value is 3]
{
hi=2, hello=5, world=5, boy=3}
4.迭代器
按顺序提供对元素的访问
1、Iterator
Iterable<T>接口的继承者(包括Set和List)可通过方法iterator()获得迭代器。一旦迭代器通过最后一个元素,它就不能用于检索元素;迭代器也不能指向以前的元素。要再次检索集合,需重新创建新的迭代器。
val list1 = listOf("hi", "hello", "world", "boy")
val iter:Iterator<String> = list1.iterator()
while (iter.hasNext()){
//hasNext判断的是迭代的次数与集合大小是否相等,cursor != size
//next一次,取出当前元素,迭代次数就+1,cursor = i + 1;return (E) elementData[lastRet = i];
println(iter.next())
}
for和forEach
for (item in list1){
println(item)
}
list1.forEach {
println(it) }
2、List迭代器
对于列表,ListIterator支持双向迭代
val listTer = list1.listIterator()
while (listTer.hasNext()){
print(listTer.next() + " ")
}
println()
while (listTer.hasPrevious()){
print(listTer.previous() + " ")
}
println()
hi hello world boy
boy world hello hi
3、可变迭代器
可变集合的迭代器,可以操作集合
删除操作,删除的是当前位置的前一个元素,所以remove()必须在next()之后。
val list2 = mutableListOf("one", "two", "three")
val iter2 = list2.iterator()
iter2.next()
iter2.remove()//iterator值提供了remove方法
println(list2)
[two, three]
ListIterator还提供了插入和替换元素的方法,操作的是迭代器指向的当前位置
val list3 = mutableListOf("one", "two", "three")
println(list3)
val iter3 = list3.listIterator()
iter3.add("hi")
iter3.next()
println(list3)
iter3.set("hello")
println(list3)
[one, two, three]
[hi, one, two, three]
[hi, hello, two, three]
4.区间和数列
1、只有整数类型区间(IntRange、LongRange、CharRange)
for (i in 0..5){
print("$i ")
}
println()
0 1 2 3 4 5
反向迭代 downTo
for (i in 5 downTo 0){
print("$i ")
}
println()
5 4 3 2 1 0
任意步长迭代 step
for (i in 5 downTo 0 step 2){
print("$i ")
}
println()
5 3 1
2、数列整数类型的区间可视为等差数列。
数列具有三个基本属性:first、last、step。后续元素是前一个元素加上step。
5.序列
序列(Sequence<T>)提供了与Iterable相同的函数。
1、构造
由元素
val sq = sequenceOf<Int>(1, 2, 3)
由Iterable
val list = listOf<Int>(1, 2, 3)
val sq1 = list.asSequence()
由函数
可以将第一个元素指定为显式值或函数调用的结果。 当提供的函数返回 null
时,序列生成停止。因此,以下示例中的序列是无限的。
val sq2 = generateSequence(1) {
if(it < 20) it * 2 else null }
println(sq2.toList())
[1, 2, 4, 8, 16, 32]
由组块
val sq3 = sequence<Int> {
yield(1)
yieldAll(5..10)
yieldAll(generateSequence(20) {
it + 1 })
}
println(sq3.take(10).toList())
[1, 5, 6, 7, 8, 9, 10, 20, 21, 22]
2、序列操作
无状态
有状态
6.集合操作
1、映射
映射转换,从一个集合元素上的函数结果创建另一个集合。
val set = setOf(1, 2, 3)
val mSet = set.map {
it * 2 }
val mSet1 = set.mapIndexed{
index, i ->
index * i
}
val mNSet = set.mapNotNull {
if (it == 2) null else it * 2 }
println(mSet)
println(mSet1)
println(mNSet)
[2, 4, 6]
[0, 2, 6]
[2, 6]
Map集合即可转换值,也可转换键,调用map转换得到的是一个List集合
val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3)
val list: List<Int> = map.map {
it.value }//list
val map1: Map<String, Int> = map.mapKeys {
it.key.uppercase() }
val map2: Map<String, Int> = map.mapValues {
it.value * 2 }
println(list)
println(map1)
println(map2)
[1, 2, 3]
{
KEY1=1, KEY2=2, KEY3=3}
{
key1=2, key2=4, key3=6}
2、合拢
合拢转换,根据两个集合中相同位置的元素构建配对。zip()返回的是Pair对象的列表List(键值对列表)。只有继承了Iterable接口的List、Set集合和数组Array可以实现合拢,Map没有。
val list1 = listOf("red", "brown", "grey")
val animals = listOf("fox", "bear", "wolf")
val twoAnimal = listOf("fox", "bear")
val zList1 = list1 zip animals
val zList2 = list1.zip(twoAnimal)
list1.zip(animals){
a, b -> println("$a $b")}
red fox
brown bear
grey wolf
要分割键值对列表,用unzip(),得到的是一个Pair对象,键为第一个列表,值为第二个列表。
val unPair: Pair<List<String>, List<String>> = zList1.unzip()
println(unPair.first)
println(unPair.second)
[red, brown, grey]
[fox, bear, wolf]
3、关联
关联转换,允许集合元素与其关联的某些值构建Map集合。
associateWith(),创建一个Map,原始集合中的元素是键,转换函数返回值。
val list = listOf("one",