前言
通过对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,并提供更多的方法和属性,使其更加完善,可移植性更好,更加简洁。