Kotlin学习笔记三:联系人列表


前言

       通过对kotlin的学习,对于String类中的方法和set,list,map等有了更深的了解,接下来是用一些基础的知识来写一个联系人列表效果如下图: 


一、主要涉及到的知识点

      首先每个首字母对应的是一个集合,集合里面保存着当前对应首字母的数据,可能有一个,也可能有多个。保存多个数据我们可以想到运用集合,姓名和拼音一一对应,可以用Map来存储,一个首字母对应多个联系人,我们可以想到运用map。因为在map中,一个key对应一个value,但一个value可以由多个key对应。

二、代码解释

1.先定义一个类ContractPerson

完整代码如下:

import net.sourceforge.pinyin4j.PinyinHelper
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType
import java.util.*

class InvalidNameFormatException(message: String): Exception(message)

class ContractPerson {
    // 用于存储联系人姓名和拼音的Map
    private val storageMap: MutableMap<Char, MutableMap<String,String>> = mutableMapOf()
    //先获取名字
    fun inputPersonName () :String{
        println("请输入想要添加联系人的姓名(若退出请输入“退出程序”):")
        Scanner(System.`in`).also {
            while(true){
                try {
                    val name :String = it.next()
                    if(!name.matches(Regex("[\\u4e00-\\u9fa5]+"))) {
                        throw InvalidNameFormatException("姓名格式不正确,请输入中文字符。")
                    }
                    return name
                }catch (e : InvalidNameFormatException){
                    println(e.message)
                    it.nextLine()
                }
            }
        }
    }

    //转换为拼音并用Map存储
    fun addNameToStorage(name:String){
        val currentName: String = name
        var storageName: String = ""
        var initial :Char = 0.toChar()

        val format = HanyuPinyinOutputFormat()
        format.caseType = HanyuPinyinCaseType.LOWERCASE    //转化成小写
        format.toneType = HanyuPinyinToneType.WITHOUT_TONE

        for(i in currentName.indices){
            val py = PinyinHelper.toHanyuPinyinStringArray(currentName[i],format)
            // 首字母大写处理
            val formattedPy = py[0].replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
            storageName += formattedPy
            if(i == 0){
                initial = formattedPy[0]
            }
        }
        //将其用Map存储起来
        storageMap.computeIfAbsent(initial) { mutableMapOf() }[currentName] = storageName
    }

    //打印出来
    fun printPersonName() {
        /**
         * 取出 storageMap 中的所有键:
         * storageMap.keys 返回所有联系人姓名。
         * 根据拼音排序:
         * compareBy { storageMap[it] } 指定排序的依据
         * 是 storageMap 中键对应的拼音值。
         * 这意味着联系人将按拼音排序,而不是按姓名本身的字母顺序。
         * 转换为 SortedMap:
         * toSortedMap 使用 compareBy 指定的比较器创建一个新的
         * SortedMap,这个 SortedMap 中的联系人将按照拼音排序。
         */
        val sortedMap = storageMap.toSortedMap()
        sortedMap.forEach { (initial, namesMap) ->
            println(initial.uppercaseChar())
            namesMap.toSortedMap(compareBy { namesMap[it] }).forEach { (name, pinyin) ->
                println("$name-$pinyin")
            }
        }
    }
}

fun main() {
    val contractPerson = ContractPerson()
    while (true){
        val inputName : String = contractPerson.inputPersonName()
        if(inputName  == "退出程序"){
            break
        }
        contractPerson.addNameToStorage(inputName)
        contractPerson.printPersonName()
    }
}

2.对方法的解读

先定义一个私有属性storageMap,用于存储列表首字母和联系人。

// 用于存储联系人姓名和拼音的Map
//在kotlin中这样对应是允许的
private val storageMap: MutableMap<Char, MutableMap<String,String>> = mutableMapOf()

定义一个方法,作用是从终端中接收用户的输入,并抛出异常。

    fun inputPersonName () :String{
        println("请输入想要添加联系人的姓名(若退出请输入“退出程序”):")
        Scanner(System.`in`).also {
            while(true){
                try {
                    val name :String = it.next()
                    if(!name.matches(Regex("[\\u4e00-\\u9fa5]+"))) {
                        //这里需要重新创建一个异常类
                        throw InvalidNameFormatException("姓名格式不正确,请输入中文字符。")
                    }
                    return name
                }catch (e : InvalidNameFormatException){
                    println(e.message)
                    it.nextLine()
                }
            }
        }
    }

 然后在创建一个方法,用于将输入的名字转换为拼音,这里还需要导入一个将中文转化为拼音的jar包。

    //转换为拼音并用Map存储
    fun addNameToStorage(name:String){
        val currentName: String = name
        var storageName: String = ""
        var initial :Char = 0.toChar()

        val format = HanyuPinyinOutputFormat()
        format.caseType = HanyuPinyinCaseType.LOWERCASE    //转化成小写
        format.toneType = HanyuPinyinToneType.WITHOUT_TONE

        for(i in currentName.indices){
            val py = PinyinHelper.toHanyuPinyinStringArray(currentName[i],format)
            // 首字母大写处理
            val formattedPy = py[0].replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
            storageName += formattedPy
            if(i == 0){
                initial = formattedPy[0]
            }
        }
        //将其用Map存储起来
        storageMap.computeIfAbsent(initial) { mutableMapOf() }[currentName] = storageName
    }

 最后在创建一个打印列表的方法。

    //打印出来
    fun printPersonName() {
        /**
         * 转换为 SortedMap:
         * toSortedMap 使用 compareBy 指定的比较器创建一个新的
         * SortedMap,这个 SortedMap 中的联系人将按照拼音排序。
         */
        val sortedMap = storageMap.toSortedMap()
        sortedMap.forEach { (initial, namesMap) ->
            println(initial.uppercaseChar())
            namesMap.toSortedMap(compareBy { namesMap[it] }).forEach { (name, pinyin) ->
                println("$name-$pinyin")
            }
        }
    }

 main函数

fun main() {
    val contractPerson = ContractPerson()
    while (true){
        val inputName : String = contractPerson.inputPersonName()
        if(inputName  == "退出程序"){
            break
        }
        contractPerson.addNameToStorage(inputName)
        contractPerson.printPersonName()
    }
}


总结

这个代码只是基础的方法用于创建一个简单的demo,并没有实现类与对象的思想。该代码只是提供了基本的方法,下一篇我会用类与对象的方法来写这个demo,并提供更多的方法和属性,使其更加完善,可移植性更好,更加简洁。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值