Kotlin学习笔记四、集合set-容器list-映射map相关

一、概述。

Kotlin中的容器分三类,分别是集合Set、队列List、映射Map,跟Java的集合set、list、map一一对应。但是kotlin里面的容器又分为只读和可变两种类型。区别在于该容器是否可以进行增、删、改等变更操作。Kotlin语言里面,对于变量的修改操作是很谨慎的,每隔变量在声明的时候就必须指定能否修改。比如我们前面讲到过的,被val修饰的变量就不能够被修改,而被var修饰的则可以被修改。

回到kotlin容器这边,kotlin默认容器为只读容器,如果要允许修改,就需要使用前缀Mutable对应的容器方法,比如MutableSet、MutableList、MutableMap分别表示可更改集合、可修改队列、可变更映射。只有可变容器才能够对内部的元素进行增、删、改操作。

Set、List、Map三者都属于容器,他们有一些共同的方法,我们先来看看有哪些共同的方法:

  1. isEmpty:判断容器是否为空;
  2. isNotEmpty:判断容器是否不为空;
  3. clear:清空容器;
  4. contains:容器是否包含指定元素;
  5. iterator:获取该容器的迭代器
  6. count:该容器里面的元素个数,相当于通过size属性获取到的数据。

另外,kotlin是允许我们在声明变量的时候 就完成初始化的,无论是基本数据类型还是这里的容器还是别的,这在java中,只有基本数据类型才可以,String也可以;但是像Set、List、Map这些集合则是不可能的。当然不同的店容器初始化方法有所不同,初始化的时候我们要注意到这些细节:
在这里插入图片描述

我们可以看到无论是数组还是容器,初始化的时候都是通过类似***of()的方法完成的

只读/可变容器一共6种,他们的增删改方法各有所不同,我们接下来仔细学习。

二、集合Set/mutableSet的操作

Set集合具有以下特征:

1、内部元素是无规则排列的,无法通过下标进行访问,只能通过迭代器或者循环来获取。
2、内部元素是不允许重复的,其原理值是通过校验hashCode来判断是否存在相同的元素,存在的话则将其覆盖。
3、因为Set是只读集合,初始化完成赋值后边不能再被更改,因此元素的变更只适用于MutableSet。
MutableSet的变更操作(增、删、改)有以下限制:
4、MutableSet的add()方法仅仅往集合中添加元素,因为Set集合是无序的,因此新加入的元素的位置是不知道到的
5、MutableSet集合没有修改元素的方法,一个元素一旦被添加,就不可被修改,除非被删除。
6、MutableSet集合的remove方法用于删除指定的元素,但无法通过下标删除指定位置的元素,这是因为MutableSet集合里面的元素本就不是按照顺序排列的。

Set集合的遍历操作,有以下三种方式:

A、for-in循环;
B、iterator迭代器循环;
C、forEach循环;

val mobilePhone: Set<String> = setOf("华为", "小米", "ViVo", "OPPO", "Apple")
println("我们查询到了以下${mobilePhone.size}款手机:")

A、for-in循环遍历:

for (item in mobilePhone){
	println("for循环得到的手机品牌是:$item")
}

B、iterator迭代器循环遍历:

var iterable = mobilePhone.iterator()
while (iterable.hasNext()){
	println("iterable迭代器循环得到的手机品牌是:${iterable.next()}")
}

C、forEach循环遍历:

mobilePhone.forEach {
	println("forEach循环得到的手机品牌是:$it")
}

三种循环输出结果都是一样的:
在这里插入图片描述
还可以移除满足指定条件的元素:

var setMutable: MutableSet<Int> = mutableSetOf(99, 88, 77, 66, 55, 44, 33, 22, 11)
setMutable.remove(66)	
setMutable.add(123)	
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    setMutable.removeIf {
    	//移除元素值为55的项
        it == 55
    }
}

三、队列List/mutableList

队列是一种元素之间按照顺序排列的容器,他与集合的最大的区别就是对元素多了次序管理,也因此新增了许多的新的功能:

a、队列能够通过get方法获取到指定位置的元素,也可以通过位置下标获取到该位置的元素

b、MutableList的add方法每次都是吧元素添加到队列的末尾,但也可以通过指定下标的方式添加到指定的位置

c、MutableList的set方法是允许替换或者修改指定位置的元素的

d、MutableList可以通过removeAt(int index)的方式删除指定位置的元素。

e、队列List除了拥有跟Set集合那样的三种遍历的方式获取每隔元素外,还多了以下三种方式:

var listString:List<String> = listOf("华为", "小米", "ViVo", "OPPO", "Apple")
for (index in listString.indices){
	println("队列list还可以通过循环下标的方式获取元素:$index 位置的元素是:" +	listString.get(index))
}

for (index in 0..listString.size-1){
    println("队列list还可以通过0..listString.size-1循环的方式获取元素:$index 位置的元素是:" + listString[index])
}

for ((index, item) in listString.withIndex()){
    println("队列list还可以通过循环下标的方式获取元素:$index 位置的元素是:$item")
}

listString.indices函数持有list的下标index列表。而listString.withIndex()函数的内部实现实质上是迭代。

队列的常用方法如下:

var sortType = true
var type = "升序排列"
var listString:List<String> = listOf("华为", "小米", "Apple", "ViVo", "OPPO")

//创建可变的队列的时候,要注意,指定类型的时候要用MutableList,后面初始化的时候要用mutableListOf,否则将会是一个不可变的队列
val listMutableString:MutableList<String> = mutableListOf("华为", "小米", "Apple", "ViVo", "OPPO")
for (index in listString.indices){
	println("队列list还可以通过循环下标的方式获取元素:$index 位置的元素是:" + listString.get(index))
}

if (sortType){
	type = "升序排列"
	listString.sortedBy {
	    it.length
	}
}else{
	type = "降序排列"
	listString.sortedByDescending {
	    it.length
	}
}
listString.forEach {
	println("按$type" + "得到的数据:$it")
}
sortType = !sortType

//通过元素内容确定元素所在的位置
var index = listString.indexOf("ViVo")
println("指定元素出现的位置是:$index")
var getItemWithIndex = listString.get(2)
println("获取指定下标元素:$getItemWithIndex")

//直接添加到队列的最后
listMutableString.add("三星")
for (item in listMutableString){
	println("通过add添加后的数据情况:$item")
}

//添加到指定位置
listMutableString.add(2, "努比亚")
for (item in listMutableString){
	println("通过add的下标添加后的数据情况:$item")
}

//addAll也是将新的元素或者元素组添加到队列的最后
listMutableString.addAll(mutableListOf("黑莓", "Google"))
for (item in listMutableString){
	println("通过addAll添加后的数据情况:$item")
}

//通过这种方式设置的item将会覆盖原本该位置的item元素,相当于add(index, item)功能
listMutableString.set(listMutableString.size-1, "LG")
for (item in listMutableString){
	println("通过set方法添加后的数据情况:$item")
}
var containsString = "努比亚"
println("是否包含指定的内容:$containsString:" + listMutableString.contains(containsString))
println("查询是否包含某个队列:" + listMutableString.containsAll(mutableListOf("努比亚", "LG")))

//既可以通过remove方法直接指定要删除的元素内容来删除,也可以通过在指定index位置来删除
listMutableString.remove("Google")
for (item in listMutableString){
	println("通过remove方法删除后的数据情况:$item")
}
listMutableString.removeAt(4)
for (item in listMutableString){
	println("通过removeAt方法删除后的数据情况:$item")
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
	//根据条件删除满足某种条件的item元素,相对java里面的删除操作,简单了太多。而且也无须担心线程安全问题
	listMutableString.removeIf {
	    "黑莓".equals(it)
	}
	for (item in listMutableString){
	    println("通过removeIf条件判断的方式删除后的数据情况:$item")
	}
}

//这里的截取同样遵循包前不包后的原则。
var subList = listMutableString.subList(1, 5)
for (item in subList){
	println("通过subList截取的方式获取到一个新的列表的数据情况:$item")
}
listMutableString.clear();
println("listMutableString是空的吗?  " + listMutableString.isEmpty())

最后提两个关于队列mutableList的高级语法:add<= = =>“+=”,remove<===>“-=”

listMutableString.add("中兴") <===> listMutableString += "中兴"
listMutableString.remove("中兴") <===> listMutableString -= "中兴"

val list = mutableListOf("华为", "荣耀")
list.add("小米")
list += "OPPo"
list += "VIVO"

list.forEach {
    println("list执行添加 add/ +=之后的结果输出:it====$it")
}

list.remove("VIVO")
list -= "OPPo"

list.forEach {
    println("list执行移除 remove/ -=之后的结果输出:it====$it")
}

输出结果:

list执行添加 add/ +=之后的结果输出:it====华为
list执行添加 add/ +=之后的结果输出:it====荣耀
list执行添加 add/ +=之后的结果输出:it====小米
list执行添加 add/ +=之后的结果输出:it====OPPo
list执行添加 add/ +=之后的结果输出:it====VIVO
list执行移除 remove/ -=之后的结果输出:it====华为
list执行移除 remove/ -=之后的结果输出:it====荣耀
list执行移除 remove/ -=之后的结果输出:it====小米

四、映射Map/mutableMap

映射Map内部保存的是一组键值对(key-value), 也就是说,每个元素都由两部分组成,第一部分是元素的键key,相当于元素的名字或者索引,第二部分是元素的值value,存放着元素的详细信息。元素的键与值(key-value)都是一一对应的,相同的键key或者说索引key指向的值value是唯一的。所以映射中每个元素的键key各不相同,这个特性使得映射的变更操作与队列存在一些不同之处(类似Java中的Map集合,另外Kotlin里面的Map映射的变更操作也要有mutableMap来完成,Map是不可变的映射集合):

1、映射的containsKey()方法可以判断映射中是否存在指定键名key的元素value。contaisValue()方法可以判断映射中是否存在指定键值value的元素value;

2、mutableMap集合的普通put()方法不单单是添加元素,每次调用put()方法时,映射会现根据键key去寻找同键名key的元素value,如果没有找到就添加新的元素value,如果找到了,就直接用新的元素value覆盖旧的元素value;

3、mutableMap的remove()方法是通过键key来删除元素的;

4、调用mapOf()和mutableMapOf()方法初始化映射集合时,有两种方式可以表达单个键值对元素,一是采用“key to value”的形式,二是采取Pair配对的形式:Pair(key,value):

//键名key to 键值value的方式初始化映射
var goodsToMap: Map<String, String> = mapOf(
    "苹果" to "iphone8",
    "华为" to "Mate 20",
    "小米" to "小米6",
    "OPPO" to "OPPO R11",
    "步步高" to "Vivo x95",
    "Meizu" to "魅族Pro6s"
)
//Pair的方式初始化映射:
var goodsPairMap: MutableMap<String, String> = mutableMapOf(
	Pair("苹果", "iphone8"),
	Pair("华为", "Mate 20"),
	Pair("小米", "小米6"),
	Pair("OPPO", "OPPO R11"),
	Pair("步步高", "Vivo x95"),
	Pair("Meizu", "魅族Pro6s")
)

映射的遍历与集合Set类似,也有for-in循环、迭代器循环、forEach便利循环三种。但是由于映射的元素是一个键值对,因此它的遍历方式与集合Set又稍有不同:

1、for-in循环:

for-in循环取出来的是映射的元素键值对,若要获取该元素的键key和值value,还需要分别访问,具体如下:

for (itemToMap in goodsToMap) {
        println("for-in循环,key--->>>${itemToMap.key}, value--->>>${itemToMap.value}")
    }
2、迭代器遍历:

映射通过hashNext()函数获取下一个迭代器,然后再通过迭代器的next()方法获取元素键值对(key-value),最后通过键值对(获取到元素的键key和值value。具体如下:

var iteratorMap = goodsToMap.iterator()
while (iteratorMap.hasNext()) {
	var itemIterator = iteratorMap.next()
	println("iterator迭代循环,key--->>>${itemIterator.key}, value--->>>${itemIterator.value}")
}
3、forEach遍历:

映射的forEach方法内部依旧采用匿名函数的形式获取到元素键值对(key-value),不过forEach遍历函数需要AndroidSDKAPI24以上的版本支持,这点需要注意。具体如下:

goodsToMap.forEach {
  println("forEach迭代循环,key--->>>${it.key}, value--->>>${it.value}")
}
4、关于MutableMap集合的put、remove、replace等方法测操作如下:
goodsPairMap.put("HONOR", "荣耀 V30")
goodsPairMap.remove("Meizu")
goodsPairMap.replace("步步高", "VIVO")
goodsPairMap.remove("步步高")
goodsPairMap.put("VIVO", "Vivo x95")

if (goodsPairMap.containsKey("VIVO")){
	println("通过get--key的方式获取元素---${goodsPairMap.get("VIVO")}")
}

if (goodsPairMap.containsValue("魅族Pro6s")){
	println("通过get--key的方式获取元素---${goodsPairMap.get("Meizu")}")
}else{
	println("map集合映射中不存在“Meizu---魅族Pro6s”这样的键值对")
}
goodsPairMap.clear()
if (goodsPairMap.isNullOrEmpty()) {
	println("goodsPairMap是null 或者 Empty")
}

上述各代码运行结果如下:
在这里插入图片描述

============================================================================================================================================================

以下是20200904新增更新的笔记

5、在Kotlin里面我们也可以像在Java里面那样创建各种数据类型汇集在一起的map集合:
var str = StringBuffer("你大爷永远是你大爷")
var mutMap = mutableMapOf<String, Any>("任缥缈"  to "缥缈剑法",            //value为字符串
                                       "宫本总司" to "无极剑法-神魔一念",   //value为字符串
                                       "西经无缺" to "摩柯无量",           //value为字符串
                                       "key" to  123456,                 //value为数字
                                       "boolean" to true,                //value为布尔值
                                       "char" to 'A',                    //value为字符
                                        "StringBuffer" to str)           //value为对象

上面的mutMap 等价于Java的这个写法:

StringBuffer str = new StringBuffer("你大爷永远是你大爷");
Map<String, Object> map = new HashMap<>();
map.put("任缥缈", "缥缈剑法");
map.put("宫本总司", "无极剑法-神魔一念");
map.put("西经无缺", "摩柯无量");
map.put("key", 123456);
map.put("boolean", true);
map.put("char", 'A');
map.put("StringBuffer", str);

因此我们可以知道:kotlin里面的“Any”对象 等价于 Java里面的Object对象。

mutMap.forEach { key, value ->
    println("forEach循环:key--->$key, value--->$value")
}

for (item in mutMap){
    println("for--in循环:key--->${item.key}, value--->${item.value}")
}

var itrator = mutMap.iterator()
while (itrator.hasNext()){
    var iteratorObj = itrator.next()
    println("iterator迭代循环:key--->${iteratorObj.key}, value--->${iteratorObj.value}")
}

最後,map的replace()方法還有另外一種實現方式:

mutMap["key"] = 963852741
println("key对应的value--->${mutMap["key"]}")
mutMap.replace("key", 123456789)
println("key对应的value--->${mutMap["key"]}")

結果如下:

key对应的value--->963852741
key对应的value--->123456789

因此我們可以知道:

kotlin裏面,mutMap.replace(key, value)等價於:mutMap[key] = value,這一操作方式跟數組很類似了。

關於map添加元素,出了直接的 key to value这种方式外,还有Pair(key, value)方式,关于Pair这个类,我们有一些小的知识点:

var pair = Pair("hello", "kotlin")
//方式一、
var first = pair.first;
var second = pair.second;
println("first === $first, second === $second")
//方式二、
var (x, y) = pair
println("x === $x, y === $y")

输出结果如下:

first === hello, second === kotlin
x === hello, y === kotlin

我们可以看到:
其实pair.first对应的就是map 的key值,pair.second对应的就是map的value值。
而(x, y)的写法感觉很像是数学里面的坐标,或者说Java自定义View里面Point对象的point.x/point.y等等。

最后也还有一个Triple对象,用法跟Pair一样:

var mTriple = Triple("key", 2, 33)
var firstTriple = mTriple.first
var secondTriple = mTriple.second
var thirdTriple = mTriple.third
println("firstTriple === $firstTriple, secondTriple === $secondTriple, thirdTriple === $thirdTriple")

var (a, b, c) = mTriple
println("a === $a, b === $b, c === $c")

输出结果如下:

firstTriple === key, secondTriple === 2, thirdTriple === 33
a === key, b === 2, c === 33
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值