Scala 字符串操作

60 阅读3分钟

一、Scala 字符串的两种定义方式

先从最基础的字符串定义开始,Scala 支持两种常用的字符串声明形式:

代码实现

package string

object string01 {
  def main(args: Array[String]): Unit = {
    val str1 = "静夜思  李白  420117200501256578"

    val str2 =
      """ 静夜思
          李白
        """
        println(str1)
        println(str2)
  }
}

二、字符串基础操作:索引、长度、截取、转数字

掌握了定义方式,接下来是字符串的核心操作 —— 这是后续实战的基础:

代码实现

package string
/*
字符串:
常见操作
1.获取单个字符
2.字符串的长度,空格也是有效的字符,他也会占长度
3.字符串的截取:从当前字符串中,截取一段出来 subString(起点下标,终点下标——不包含)
4.转成数字
 */

object string02 {
  def main(args: Array[String]): Unit = {
    val str1 = "hello scala"
    //字符串(下标),下标从0开始
    println(str1(0))
    println("字符串的长度是: " + str1.length)

    //把 ello 这四个字符取出来
    val str2 = str1.substring(1,5)
    println(str2)
    //把 cal 这个三个字符取出来?

    val str3 = "我的手机号的第三位是3"
    //把 3 截取出来
    val str4 = str1.substring(10,12)//str4是一个字符串"3"
    println(str4 + 10)
    val n = str4.toInt
    println(n + 1)

  }
}

三、实战:用 Scala 提取身份证信息

学会基础操作后,我们做一个实用案例 ——从身份证号中提取性别、年龄、所属省市,这也是企业开发中常见的字符串解析场景。

需求分析

身份证号(18 位)包含的信息:

  • 前 2 位:省份编码
  • 第 7-14 位:出生年月日
  • 倒数第 2 位:性别(奇数为男,偶数为女)

代码实现

package string

import java.time.LocalDate

object string03 {
  def main(args: Array[String]): Unit = {
    // 1. 定义身份证前两位对应的省市映射表(补充缺失的regionMap)
    val regionMap = Map(
      "11" -> "北京市", "12" -> "天津市", "13" -> "河北省", "14" -> "山西省", "15" -> "内蒙古自治区",
      "21" -> "辽宁省", "22" -> "吉林省", "23" -> "黑龙江省", "31" -> "上海市", "32" -> "江苏省",
      "33" -> "浙江省", "34" -> "安徽省", "35" -> "福建省", "36" -> "江西省", "37" -> "山东省",
      "41" -> "河南省", "42" -> "湖北省", "43" -> "湖南省", "44" -> "广东省", "45" -> "广西壮族自治区",
      "46" -> "海南省", "50" -> "重庆市", "51" -> "四川省", "52" -> "贵州省", "53" -> "云南省",
      "54" -> "西藏自治区", "61" -> "陕西省", "62" -> "甘肃省", "63" -> "青海省", "64" -> "宁夏回族自治区",
      "65" -> "新疆维吾尔自治区", "71" -> "台湾省", "81" -> "香港特别行政区", "82" -> "澳门特别行政区"
    )

    // 测试用例修正:改为18位合法身份证(原17位无效)
    // val str = scala.io.StdIn.readLine("请输入你要判断的身份证号: ") // 恢复键盘输入
    val str = "430052200006110043"

    // 2. 核心修正:先校验身份证长度(18位),这是所有逻辑的前提
    if (str.length == 18) {
      try {
        // ========== 1. 性别判断 ==========
        // 取出倒数第二位(索引16),转Int(解决类型问题)
        val gender = str.substring(16, 17).toInt
        println(s"性别位数字:$gender")
        if (gender % 2 == 1) {
          println("这是一个帅哥")
        } else {
          println("这是一个小姑娘")
        }

        // ========== 2. 年龄计算(精确到生日) ==========
        // 提取出生年月日(身份证第7-14位:索引6-13)
        val birthYear = str.substring(6, 10).toInt   // 出生年
        val birthMonth = str.substring(10, 12).toInt // 出生月
        val birthDay = str.substring(12, 14).toInt   // 出生日
        println(s"出生日期:$birthYear$birthMonth$birthDay日")

        // 精确计算年龄:判断生日是否已过
        val now = LocalDate.now()
        val currentYear = now.getYear
        var age = currentYear - birthYear
        if (birthMonth > now.getMonthValue || (birthMonth == now.getMonthValue && birthDay > now.getDayOfMonth)) {
          age -= 1 // 生日未过,年龄减1
        }
        println(s"今年${age}岁")

        // ========== 3. 省市判断 ==========
        val pro = str.substring(0, 2) // 取出前两位省份编码
        val province = regionMap.get(pro)
        province match {
          case Some(name) => println(s"所属省份/直辖市:$name")
          case None => println(s"没有编号为${pro}的省份")
        }

      } catch {
        // 处理非数字转换异常(比如身份证含字母)
        case _: NumberFormatException =>
          println("身份证号格式错误:出生日期/性别位必须是数字")
        // 处理索引越界(理论上18位校验后不会触发,兜底用)
        case _: StringIndexOutOfBoundsException =>
          println("身份证号格式错误:索引越界")
      }
    } else {
      // 长度不合法的提示
      println(s"${str}不是一个合法的身份证号,长度不对(需18位,当前${str.length}位)")
    }
    // } // 循环输入的闭合括号(如需循环可取消注释)
  }
}