集合相关:
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用。
集合的分类:
在Kotlin中,明确的区分了可变和只读的集合(list, set, map等),明确的确定了集合的可读性,有助于良好的编码,以及便于Bug的规避。
Iterable接口是最基本的接口,声明了Kotlin中集合的通用方法。
MutableIterable接口继承于Iterabl接口,并重写了iterator方法,从该接口继承的类可以表示为可以被迭代并且支持在迭代期间移除元素的元素序列。
Collection
MutableCollection
Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。
Kotlin没有专门的语法用来创建set,可以使用标准库中的方法, 比如setOf(),mutableSetOf()。
下面看一段示例代码:
val setTea: Set = setOf("E", "F", "B", "C", "A", "D", "F", "B")
for (item in setTea) {
println(item)
}
// Log打印
E
F
B
C
A
从示例代码中,我们可以清晰的看出
1. Set中没有重复的对象
2. Set中对象不按特定的方式排序
上面提到了,Set中不能存放重复的对象,对于Kotlin中,标准的数据类型,比如基本数据类型、String等都有了相应的判定方式,如果我们自定义了类,该如何判断对象是不是重复的呢?
data class Book(var name: String, var page: Int, var author: String) {
override fun hashCode(): Int {
return this.name.hashCode()
}
override fun equals(other: Any?): Boolean {
if (other is Book) {
return this.page == other.page
}
return super.equals(other)
}
}
现自定义了一个Book类,同时重写了hashCode()和equals()两个函数,其中,Book实例的hashCode()的返回值为name属性的hashCode()值,而equals()函数判断两个Book实例是否向相等的标准为page属性。
val bookA = Book("A", 20, "Jone")
val bookB = Book("A", 21, "Green")
val bookC = Book("C", 20, "Mark")
val bookD = Book("D", 22, "Node")
val bookE = Book("A", 20, "Blue")
var setBook = setOf(bookA, bookB, bookC, bookD, bookE)
println(setBook.size)
for (item in setBook) {
println("item:$item , hashCode: ${item.hashCode()}")
}
// Log打印
4
item:Book(name=A, page=20, author=Jone) , hashCode: 65
item:Book(name=A, page=21, author=Green) , hashCode: 65
item:Book(name=C, page=20, author=Mark) , hashCode: 67
item:Book(name=D, page=22, author=Node) , hashCode: 68
先不看Log打印,我们先看往setBook中添加的元素,根据我们刚才自定义Book的类,我们可以分析得到。
现在在看Log打印,在setBook中有4个元素bookA、bookB、bookC、bookD.再从上面分析的可以认为,bookA、和BookE是重复对象的Book对象。
对于Set而言,存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。刚才问的问题也就呼之欲出了,在Kotlin中,判断两个对象的是否重复标准是hashCode()和equals()两个参考值,也就是说只有两个对象的hashCode值一样与equals()为真时,才认为是相同的对象。所以自定义的类必须要要重写hashCode()和equals()两个函数。
MutableSet接口继承于Set, MutableCollection,对Set的扩展,添加了对元素添加和删除的操作。
常用API:
查询操作
元素操作
批量操作
var setMulable = mutableSetOf(bookA, bookB, bookC, bookD, bookE)
setMulable.add(Book("Add", 20, "Floor"))
println(setMulable.remove(bookA))
println(setMulable.remove(bookE))
for (item in setBook) {
println("item:$item , hashCode: ${item.hashCode()}")
}
// Log
true
false
item:Book(name=A, page=21, author=Green) , hashCode: 65
item:Book(name=C, page=20, author=Mark) , hashCode: 67
item:Book(name=D, page=22, author=Node) , hashCode: 68
item:Book(name=Add, page=20, author=Floor) , hashCode: 65665
在Java中,Set接口有两个主要的实现类HashSet和TreeSet:
Kotlin并没有HashSet、TreeSet和LinkedHashSet。假如,实际开发过程中,如果用到了这三个中某一个Set,比如想通过hashCode来存取对象,此时该如何是好呢?鉴于与Java的兼容性,JB大婶们已经为我们,封装了生成HashSet、TreeSet或者LinkedHashSet的函数,我们可以用Java中的这三个类。
List的特征是其元素以线性方式存储,集合中可以存放重复对象。
List
查询操作
批量操作
索引查询操作
搜索操作
迭代器
MutableList
修改操作
批量操作
索引操作
与set一样,Kotlin并没有提供创建List的函数,如果想创建一个List,可以调用标准库中的方法,listOf() , mutableListOf()。
listOf()是使用ArrayList实现的,返回的list是只读的,其内存效率更高。在开发过程中,可以尽可能的多用只读List,可以在一定程度上提高内存效率。
val bookA = Book("A", 20, "Jone")
val bookB = Book("B", 21, "Green")
val bookC = Book("C", 22, "Mark")
val bookD = Book("D", 23, "Node")
val bookE = Book("E", 24, "Blue")
val listBook = listOf(bookA, bookB, bookC, bookD, bookE)
创建了一个只读List,我们可以做以下操作:
索引检索
// 获取位置0处的元素
listBook.get(0)
// 获取bookA第一次出现的位置
listBook.indexOf(bookA)
// 获取bookA最后一次出现的位置
listBook.lastIndexOf(bookB)
遍历List
扩展函数foreach
listBook.forEach (::println )
for循环
for (book in listBook) {
println(book)
}
迭代器
while (iterator.hasNext()) {
println(iterator.next())
}
class Controller {
private val _items = mutableListOf()
val items: List get() = _items.toList()
}
toList是一个扩展函数,其只是单纯的赋值list内的内容,从而返回的是一个只读的List.
Map是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口。从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Kitlin中,与list、set一样的是,Map也分为只读map和可变两种Map。
Kotlin中,创建Map时,需调用标准库中的系列函数,如mapOf(),mutableMapOf()
Entry
Pair类用来存储两个值,这两个值可以是任何类型的,可以用于任何场景,比如Map,List.
Pair类有扩展函数 to,可快速创建Pair类的实例。
基于Pair扩展函数 to
val bookA = Book("A", 20, "Jone")
val bookB = Book("A", 21, "Green")
val bookC = Book("C", 20, "Mark")
val bookD = Book("D", 22, "Node")
val bookE = Book("A", 20, "Blue")
val map= mapOf(1 to bookA, 2 to bookB, 3 to bookC, 4 to bookD, 5 to bookE)
var mapMutable = mutableMapOf(1 to bookA, 2 to bookB, 3 to bookC, 4 to bookD, 5 to bookE)
基于Pair
val mapPair = mapOf(Pair(1, bookA), Pair(1, bookB))
创建一个空的Map
val mapEmpty = emptyMap()
HashMap
val hashMap = hashMapOf(1 to bookA, 2 to bookB)
LinkedHashMap
val linkedHashMap = linkedMapOf(1 to bookA, 2 to bookB)
注
判断映射中元素的数量
var mapMutable = mutableMapOf(1 to bookA, 2 to bookB, 3 to bookC, 4 to bookD, 5 to bookE)
val size = mapMutable.siz // size = 5
Map元素中Key的集合
val setKey = map.keys
setKey.forEach(::print) // Log: 1,2,3,4,5
var setMutableKey = mapMutable.keys
setMutableKey.forEach(::print) // Log: 1,2,3,4,5
Map中元素的集合
val setValues = map.values
setValues.forEach(::println)
// Log
// Book(name='A', page=20, author='Jone')
// Book(name='A', page=21, author='Green')
// Book(name='C', page=20, author='Mark')
// Book(name='D', page=22, author='Node')
var setMutableValues = mapMutable.values
setMutableValues.forEach(::println)
// Log
// Book(name='A', page=20, author='Jone')
// Book(name='A', page=21, author='Green')
// Book(name='C', page=20, author='Mark')
// Book(name='D', page=22, author='Node')
Map中元素的键/值对的集合
val setEntry = map.entries
setEntry.forEach{
println("key: ${it.key} , value: ${it.value}")
}
var setMutableEntry = mapMutable.entries
setMutableEntry.forEach{
println("key: ${it.key} , value: ${it.value}")
}
//Log
key: 1 , value: Book(name='A', page=20, author='Jone')
key: 2 , value: Book(name='A', page=21, author='Green')
key: 3 , value: Book(name='C', page=20, author='Mark')
key: 4 , value: Book(name='D', page=22, author='Node')
key: 5 , value: Book(name='A', page=20, author='Blue')
注:
判断Mpa是否为空
map.isEmpty()
判断Map是否包含某个Key
map.containsKey(2)
判断Map是否包含某个元素
map.containsValue(bookA)
查询Map中指定Key的元素,若存在,返回元素值,否则返回nul
map.get(2)
添加元素
// 将指定的[value]与映射中指定的[key]关联
//
val valuePut: Boo = mapMutable.put(6, bookE)
移除元素
// 移除映射中指定Key的元素,
// 返回被移除的元素,若指定的Key的元素不存在,返回null
val valueRemove: Book = mapMutable.remove(6, bookE)
清空整个映射
map.clear()- 清空映射