scala中的字符串

55 阅读4分钟

一、Scala 中字符串的两种核心定义格式

Scala 支持不可变字符串(String)  和可变字符串(StringBuilder)  两类核心定义方式,同时字符串字面量有两种书写形式,具体如下:

1. 字面量定义(不可变,基于 Java String)

Scala 直接复用 Java 的 String 类型,不可变特性意味着字符串内容一旦创建无法修改,是最常用的方式。

  • 双引号("") :标准格式,支持转义字符(\n\t" 等)。
  • 三引号("""""") :原生字符串格式,无需转义,适合多行文本 / 含特殊字符的场景。

scala

// 1. 双引号定义(支持转义)
val str1: String = "Hello Scala!\n你好,Scala!"
println(str1)
// 输出:
// Hello Scala!
// 你好,Scala!

// 2. 三引号定义(原生字符串,无转义)
val str2: String = """Hello "Scala"!
路径:C:\scala\code"""
println(str2)
// 输出:
// Hello "Scala"!
// 路径:C:\scala\code

2. 可变字符串(StringBuilder)

用于频繁修改字符串的场景(如拼接、替换),避免不可变 String 频繁创建新对象的性能损耗:

scala

val sb = new StringBuilder("Hello")
sb.append(" Scala")  // 追加
sb.insert(5, ",")    // 插入
sb.update(0, 'h')    // 修改字符
println(sb.toString) // 输出:hello, Scala

二、Scala 字符串常用方法

Scala 字符串(String 类型)兼容所有 Java String 方法,同时扩展了更简洁的 Scala 风格方法,核心常用方法如下:

方法功能说明示例
length获取字符串长度"abc".length → 3
charAt(index)获取指定索引的字符"abc".charAt(1) → 'b'
substring(start[, end])截取子串(end 可选,默认到末尾)"abcde".substring(1,3) → "bc"
split(regex)按正则分割字符串为数组"a,b,c".split(",") → Array("a","b","c")
trim去除首尾空白字符" abc ".trim → "abc"
stripPrefix/prefix去除前缀 / 判断前缀"scala.txt".stripPrefix("scala") → ".txt"
stripSuffix/suffix去除后缀 / 判断后缀"scala.txt".endsWith("txt") → true
replace(old, new)替换所有匹配的子串"abac".replace("a", "x") → "xbxc"
replaceFirst/replaceAll正则替换(首次 / 全部)"a1b2".replaceAll("\d", "") → "ab"
toLowerCase/toUpperCase大小写转换"Scala".toUpperCase → "SCALA"
contains(sub)判断是否包含子串"abc".contains("b") → true
indexOf/substring查找子串索引(无则返回 -1)"abc".indexOf("c") → 2
isEmpty/nonEmpty判断是否为空 / 非空"".isEmpty → true
mkString集合转字符串(配合字符串拼接)Array(1,2,3).mkString(",") → "1,2,3"
interpolate字符串插值(s/f 插值器)val name = "Scala"; s"Hello $name" → "Hello Scala"

核心示例:

scala

// 1. 插值器(最常用)
val age = 20
val sStr = s"年龄:$age"                  // 普通插值 → "年龄:20"
val fStr = f"圆周率:${Math.PI}%.2f"     // 格式化插值 → "圆周率:3.14"
val rawStr = raw"路径:C:\scala"         // 原生插值(不转义)→ "路径:C:\scala"

// 2. 分割与拼接
val arr = "a,b,c".split(",")             // Array("a","b","c")
val joinStr = arr.mkString("|")          // "a|b|c"

// 3. 前缀/后缀判断
val fileName = "data.csv"
fileName.startsWith("data")              // true
fileName.endsWith("csv")                 // true

// 4. 正则匹配
val regex = "^[0-9]{6}$".r               // 6位数字正则
regex.matches("123456")                  // true

三、身份证号码的基本格式(中国大陆)

中国大陆居民身份证号分为 18 位(主流)  和 15 位(旧版,已逐步淘汰) ,核心规则如下:

1. 18 位身份证格式(GB11643-1999 标准)

结构:6位地址码 + 8位出生日期码 + 3位顺序码 + 1位校验码

部分长度说明
地址码6 位前 2 位:省级行政区代码(如 11 = 北京、31 = 上海);中间 2 位:市级;后 2 位:县级
出生日期码8 位格式为 YYYYMMDD(如 19900101=1990 年 1 月 1 日)
顺序码3 位同一地区、同日出生人员的排序码;第 3 位奇数 = 男性,偶数 = 女性
校验码1 位0-9 或 X(大写),通过前 17 位计算得出(ISO 7064:1983.MOD 11-2 算法)

2. 15 位身份证格式(旧版)

结构:6位地址码 + 6位出生日期码 + 3位顺序码

  • 出生日期码:YYMMDD(仅年份后两位,如 900101=1990 年 1 月 1 日);
  • 无校验码,顺序码规则同 18 位。

3. 关键校验规则(18 位)

校验码计算逻辑:

  1. 前 17 位每一位乘以加权因子(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);
  2. 求和后对 11 取余,余数对应校验码:0→1,1→0,2→X,3→9,4→8,5→7,6→6,7→5,8→4,9→3,10→2

Scala 示例:身份证格式校验

scala

/**
 * 校验18位身份证格式合法性
 * @param idCard 18位身份证号
 * @return 是否合法
 */
def isValidIdCard18(idCard: String): Boolean = {
  // 1. 基础格式校验(18位,前17位数字,最后一位数字/X)
  val idRegex = "^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([12]\d)|(3[01]))\d{3}[0-9Xx]$".r
  if (!idRegex.matches(idCard)) return false

  // 2. 校验码验证
  val weights = Array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2) // 前17位加权因子
  val checkCodes = Array('1','0','X','9','8','7','6','5','4','3','2') // 余数对应校验码
  val sum = idCard.take(17).zip(weights).map { case (c, w) => c.toString.toInt * w }.sum
  val remainder = sum % 11
  val actualCheckCode = idCard.last.toUpper // 统一转大写
  actualCheckCode == checkCodes(remainder).toString
}

// 测试
println(isValidIdCard18("110101199001011234")) // 示例(需替换为真实合法号)
println(isValidIdCard18("11010119900101123X")) // 校验码为X的场景

总结

  1. 字符串定义:不可变(双引号 / 三引号)、可变(StringBuilder);
  2. 常用方法:插值、分割、拼接、正则、前缀 / 后缀判断等;
  3. 身份证格式:18 位(地址 + 生日 + 顺序 + 校验),15 位(无校验,生日 6 位),核心需校验格式和校验码。