Kotlin入门(16)容器的遍历方式

Kotlin号称全面兼容Java,于是乎Java的容器类仍可在Kotlin中正常使用,包括大家熟悉的队列ArrayList、映射HashMap等等。不过Kotlin作为一门全新的语言,肯定还是要有自己的容器类,不然哪天Java跟Kotlin划清界限,那麻烦就大了。与Java类似,Kotlin也拥有三类基本的容器,分别是集合Set、队列List、映射Map,然后每类容器又分作只读与可变两种类型,这是为了判断该容器能否进行增删改等变更操作。Kotlin对修改操作很慎重,比如变量用val前缀表示不可修改,用var前缀表示允许修改;类默认是不允许继承的,只有添加open前缀才允许该类被继承;至于容器默认为只读容器,如果需要进行修改则需加上Mutable形成新的容器,比如MutableSet表示可变集合,MutableList表示可变队列,MutableMap表示可变映射。

既然Set/List/Map都属于容器,那么必定拥有相同的基本容器方法,具体说明如下:
isEmpty : 判断该容器是否为空。
isNotEmpty : 判断该容器是否非空。
clear : 清空该容器。
contains : 判断该容器是否包含指定元素。
iterator : 获取该容器的迭代器。
count : 获取该容器包含的元素个数,也可通过size属性获得元素数量。
初始化赋值 : Kotlin允许在声明容器变量之时进行初始赋值,这点很方便比Java先进,当然不同容器的初始化方法有所区别,具体的对应关系见下表:
只读集合Set setOf
可变集合 mutableSetOf
只读队列List listOf
可变队列MutableList mutableListOf
只读映射Map mapOf
可变映射MutableMap mutableMapOf
以上是Kotlin容器的基本方法,更具体的增删改查等用法则有所不同,下面分别介绍这三类六种容器的详细用法。

只读集合Set/可变集合MutableSet
集合是一种简单的容器,它具有以下特性:
1、容器内部的元素不按顺序排列,因此无法按照下标进行访问;
2、容器内部的元素存在唯一性,通过哈希值校验是否存在相同的元素,如果存在则覆盖之;
因为Set是只读集合,初始化赋值后便不可更改,所以元素变更的方法只适用于可变集合MutableSet,但MutableSet的变更操作尚有以下限制:
1、MutableSet的add方法仅仅往集合中添加元素,由于集合是无序的,因此不知道添加的具体位置;
2、MutableSet没有修改元素值的方法,一个元素一旦被添加,就不可被修改;
3、MutableSet的remove方法用于删除指定对象,但无法删除某个位置的元素,这是因为集合内的元素不是按顺序排列的;

对于集合的遍历操作,Kotlin提供了好几种方式,有熟悉的for循环,有迭代器循环,还有新面孔forEach循环,三种循环遍历的用法说明如下:

1、for-in循环
与Java类似,通过for语句加上in条件,即可轻轻松松依次取出集合中的所有元素。下面是运用了for-in循环的代码例子:

    btn_set_for.setOnClickListener {
        var desc = ""
        //使用for-in语句循环取出集合中的每条记录
        for (item in goodsMutSet) {
            desc = "${desc}名称:${item.name},价格:${item.price}\n"
        }
        tv_set_result.text = "手机畅销榜包含以下${goodsMutSet.size}款手机:\n$desc"
    }

  

2、迭代器循环
迭代器与指针的概念有点接近,它自身并非具体的元素,而是指向元素的存放地址,所以迭代器循环其实是遍历所有元素的地址。迭代器通过hasNext方法判断是否还存在下一个节点,如果不存在下一节点则表示已经遍历完毕;它通过next方法获得下一个节点的元素,同时迭代器自身改为指向该元素的地址。下面是运用了迭代器循环的代码例子:

    btn_set_iterator.setOnClickListener {
        var desc = ""
        val iterator = goodsMutSet.iterator()
        //如果迭代器还存在下一个节点,则继续取出下一个节点的记录
        while (iterator.hasNext()) {
            val item = iterator.next()
            desc = "${desc}名称:${item.name},价格:${item.price}\n"
        }
        tv_set_result.text = "手机畅销榜包含以下${goodsMutSet.size}款手机:\n$desc"
    }

  

3、forEach循环
不管是for-in循环还是迭代器循环,其实都脱胎于Java已有的容器遍历操作,代码书写上不够精炼。为了将代码精简做到极致,Kotlin给容器创造了forEach方法,明确指定该方法就是要依次遍历容器。forEach方法在编码时采用匿名函数的形式,内部使用it代表每个元素的对象,下面是运用了forEach循环的代码例子:

    btn_set_foreach.setOnClickListener {
        var desc = ""
        //forEach内部使用it指代每条记录
        goodsMutSet.forEach { desc = "${desc}名称:${it.name},价格:${it.price}\n" }
        tv_set_result.text = "手机畅销榜包含以下${goodsMutSet.size}款手机:\n$desc"
    }

  

结合以上有关Set的用法说明,我们发现集合在实战中存在诸多不足,主要包括以下几点:
1、集合不允许修改内部元素的值;
2、集合无法删除指定位置的元素;
3、不能通过下标获取指定位置的元素;
鉴于集合的以上缺点难以克服,故而实际开发基本用不到集合,大多数场合用的是它的两个兄弟——队列和映射。

只读队列List/可变队列MutableList
队列是一种元素之间按照顺序排列的容器,它与集合的最大区别,便是多了个次序管理。不要小看这个有序性,正因为队列建立了秩序规则,所以它比集合多提供了如下功能(注意凡是涉及到增删改的,都必须由MutableList来完成):
1、队列的get方法能够获取指定位置的元素,也可直接通过下标获得该位置的元素。
2、MutableList的add方法每次都是把元素添加到队列末尾,也可指定添加的位置;
3、MutableList的set方法允许替换或者修改指定位置的元素;
4、MutableList的removeAt方法允许删除指定位置的元素;
5、MutableList提供了sort系列方法用于给队列中的元素重新排序,其中sortBy方法表示按照升序排列,sortByDescending方法表示按照降序排列;下面是个给队列排序的代码例子:

    var sortAsc = true
    btn_sort_by.setOnClickListener {
        if (sortAsc) {
            //sortBy表示升序排列,后面跟的是排序条件
            goodsMutList.sortBy { it.price }
        } else {
            //sortByDescending表示降序排列,后面跟的是排序条件
            goodsMutList.sortByDescending { it.price }
        }
        var desc = ""
        for (item in goodsMutList) {
            desc = "${desc}名称:${item.name},价格:${item.price}\n"
        }
        tv_list_result.text = "手机畅销榜已按照${if (sortAsc) "升序" else "降序"}重新排列:\n$desc"
        sortAsc = !sortAsc
    }

  

5、队列除了拥有跟集合一样的三种遍历方式(for-in循环、迭代器循环、forEach循环),另外多了一种按元素下标循环遍历的方式,具体下标遍历的代码例子如下所示:

    btn_for_index.setOnClickListener {
        var desc = ""
        //indices是队列的下标数组。如果队列大小为10,则下标数组的取值为0到9
        for (i in goodsMutList.indices) {
            val item = goodsMutList[i]
            desc = "${desc}名称:${item.name},价格:${item.price}\n"
        }
        tv_list_result.text = "手机畅销榜包含以下${goodsMutList.size}款手机:\n$desc"
    }

  

只读映射Map/可变映射MutableMap
映射内部保存的是一组键值对(Key-Value),也就是说,每个元素都由两部分构成,第一部分是元素的键,相当于元素的名字;第二部分是元素的值,存放着元素的详细信息。元素的键与值是一一对应的关系,相同的键名指向的值对象是唯一的,所以映射中每个元素的键名各不相同,这个特性使得映射的变更操作与队列存在以下不同之处(注意增删操作必须由MutableMap来完成):
1、映射的containsKey方法判断是否存在指定键名的元素,containsValue方法判断是否存在指定值对象的元素;
2、MutableMap的put方法不单单是添加元素,而是智能的数据存储;每次调用put方法,映射会先根据键名寻找同名元素,如果找不到就添加新元素,如果找得到就用新元素替换旧元素;
3、MutableMap的remove方法,是通过键名来删除元素的;
4、调用mapOf和mutableMapOf方法初始化映射之时,有两种方式可以表达单个键值对元素。其一是采取“键名 to 值对象”的形式,其二是采取Pair配对方式形如“Pair(键名, 值对象)”,下面是这两种初始化方式的代码例子:

//to方式初始化映射
var goodsMap = mapOf("苹果" to goodsA, "华为" to goodsB, "小米" to goodsC, "欧珀" to goodsD, "步步高" to goodsE, "魅族" to goodsF)
//Pair方式初始化映射
var goodsMutMap = mutableMapOf(Pair("苹果", goodsA), Pair("华为", goodsB), Pair("小米", goodsC), Pair("欧珀", goodsD), Pair("步步高", goodsE), Pair("魅族", goodsF))

  

映射的遍历与集合类似,也有for-in循环、迭代器循环、forEach循环三种遍历手段。但是由于映射的元素是个键值对,因此它的循环遍历方式与集合稍有不同,详述如下:
1、for-in循环
for-in语句取出来的是映射的键值对元素,若要获取该元素的键名,还需访问元素的key属性;若要获取该元素的值对象,还需访问元素的value属性。下面是在映射中运用for-in循环的代码例子:

    btn_map_for.setOnClickListener {
        var desc = ""
        //使用for-in语句循环取出映射中的每条记录
        for (item in goodsMutMap) {
            //item.key表示该配对的键,即厂家名称;item.value表示该配对的值,即手机信息
            desc = "${desc}厂家:${item.key},名称:${item.value.name},价格:${item.value.price}\n"
        }
        tv_map_result.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
    }

  

2、迭代器循环
映射的迭代器通过next函数得到下一个元素,也需访问该元素的key属性获取键名,访问该元素的value属性获取值对象。下面是在映射中运用迭代器循环的代码例子:

    btn_map_iterator.setOnClickListener {
        var desc = ""
        val iterator = goodsMutMap.entries.iterator()
        //如果迭代器还存在下一个节点,则继续取出下一个节点的记录
        while (iterator.hasNext()) {
            val item = iterator.next()
            desc = "${desc}厂家:${item.key},名称:${item.value.name},价格:${item.value.price}\n"
        }
        tv_map_result.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
    }

  

3、forEach循环
映射的forEach方法内部依旧采用匿名函数的形式,同时把元素的key和value作为匿名函数的输入参数。不过映射的forEach函数需要API24及以上版本支持,开发时注意修改编译配置。下面是在映射中运用forEach循环的代码例子:

    btn_map_foreach.setOnClickListener {
        //var desc = ""
        ////映射的forEach函数需要API24及以上版本支持
        ////forEach内部使用key指代每条记录的键,使用value指代每条记录的值
        //goodsMap.forEach { key, value -> desc = "${desc}厂家:${key},名称:${value.name},价格:${value.price}\n" }
        //tv_map_result.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
        tv_map_result.text = "Map的forEach函数需要API24及以上版本支持"
    }

  

__________________________________________________________________________

打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

原文地址:https://www.cnblogs.com/aqi00/p/9645417.html

时间: 2024-10-13 04:45:22

Kotlin入门(16)容器的遍历方式的相关文章

如果要遍历除了for循环,你还知道什么?——JavaScript的各种遍历方式

如果要遍历除了for循环,你还知道什么?——JavaScript的各种遍历方式 这是曾经面试中的一道题目,当时的我用现在很潮的话讲,整个人是懵比的,我呆呆的说了句,我好像只知道for循环啊.后来回过神来,其实有很多,只是for循环是最常用的,大家常常会反应不上来其他的.下面通过自己所了解的以及网上找的资料做一些总结.希望对自己也对看到的人有帮助. 为了方便,现有数组和json对象如下: 1 var demoArr = ['Javascript', 'Gulp', 'CSS3', 'Grunt',

专题三、ArrayList遍历方式以及效率比较

一.遍历方式 ArrayList支持三种遍历方式. 1.第一种,随机访问,它是通过索引值去遍历 由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素. 代码如下: // 基本的forfor (int i = 0; i < size; i++){    value = list.get(i);} 2.第二种,foreach语句 foreach语句是java5的新特征之一,在遍历数组.集合方面,foreach为开发人员提供了极大的方便. 代码如下: for (In

ArrayList和LinkedList的几种循环遍历方式及性能对比分析

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论.通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解.阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性能对

ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解. 阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性

[数据结构与算法] 二叉树及其遍历方式

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289830.html 一.数据结构分类 (一)按逻辑结构 集合(无辑关系) 线性结构(线性表):数组.链表.栈.队列 非线性结构:树.图.多维数组 (二)按存储结构 顺序(数组)储结构.链式储结构.索引储结构.散列储结构 二.二叉树相关性质

HashMap循环遍历方式及其性能对比

主要介绍HashMap的四种循环遍历方式,各种方式的性能测试对比,根据HashMap的源码实现分析性能结果,总结结论.   1. Map的四种遍历方式 下面只是简单介绍各种遍历示例(以HashMap为例),各自优劣会在本文后面进行分析给出结论. (1) for each map.entrySet() Java 1 2 3 4 5 Map<String, String> map = new HashMap<String, String>(); for (Entry<String

【转】ArrayList和LinkedList的几种循环遍历方式及性能对比分析

原文网址:http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论.通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解.阅

二叉树的三种遍历方式的循环和递归的实现方式

///////////////////头文件:BST.h//////////////////////// #ifndef BST_H #define BST_H #include "StdAfx.h" #include<iostream> #include<stack> template<typename DataType> class BST { public: class Node { public: Node(int data=0):m_dat

js数组的4种遍历方式

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>数组的遍历方式</title> 6 <script type="text/javascript"> 7 var arr = [11, 22, 33, 55]; 8 //普通的循环遍历方式 9 function first() { 10 11 f