1.0 总体介绍
- Scala中的String类型就是Java中的String,所以可以使用Java中String的一些方法。
Scala提供了隐式转换,String也可以使用StringOps类的所有方法,此时可以把String当做字符序列,
- 可以利用foreach迭代打印每个字符:”hello”.foreach(println)
- 通过for循环打印每个字符:for (c <- “hello”) println(c)
- 也可以当做字节序列:”hello”.getBytes.foreach(println) //104 101 108 108 111(十进制ASCII编码)
- 使用过滤器:val result = “hello world”.filter(_ != ‘l’) //heo word
实际上这些方法并不都是来自类StringOps,有的还来自StringLike和WrappedString等,可到api文档查看String到StringOps的隐式转换。
1.1 字符串相等
- Scala中通过 == 比较两个对象是否相等,这点与Java不同,Java中是通过equals比较两个对象。
- Scala中==方法定义在类AnyRef中,首先会检查是否为null,然后再调用第一个对象的equals方法比较两个对象,所以比较两个字符串时不需要再进行null值判断。
在Scala语法中,从来不会使用空值,但是不排除使用java类库或者其他库时出现null的可能。
val s1 = "Hello" val s2 = "Hello" val s3 = "H" + "ello" s1 == s2 //true s1 == s3 //true
忽略大小写判断字符串相等
val s1: String = null val s2: String = null s1.toUpperCase == s2.toUpperCase //此刻报空指针错误,正确姿势如下 val a = "Marisa" val b = "marisa" a.equalsIgnoreCase(b) //true a.toUpperCase == b.toUpperCase //true
1.2 创建多行字符串
在Scala中通过3个双引号创建多行字符串,但是下例打印出来第二及之后行行首以白色空格开始
val foo = """This is a multiline String""" ------------//输出如下 This is a multiline String
可通过以下几种方法解决这个问题
- 每行都和第一行对齐
在多行字符串的最后添加stripMargin方法,第一行之外的每行行首以分隔符|开始
val speech = """Four score and |seven years ago""".stripMargin
如果不喜欢|分隔符, 可通过stripMargin方法使用任何字符
val speech = """Four score and #seven years ago""".stripMargin('#') ------------//输出如下 Four score and seven years ago
上述多行字符串实际是在行末有一个隐藏的\n换行字符,如果要把多行转成一行,可在stripMargin方法之后调用replaceAll方法,用空格替换换行符
val speech = """Four score and |seven years ago |our fathers""".stripMargin.replaceAll("\n", "") ------------//输出如下 Four score and seven years ago our fathers
多行字符串有一个好处就是可以直接输出单双引号,而不用可以避免
val s = """This is known as a |"multiline" string |or 'heredoc' syntax.""". stripMargin.replaceAll("\n", " ") ------------//输出如下 This is known as a "multiline" string or 'heredoc' syntax.
1.3 分隔字符串
通过split方法分隔字符串,返回字符串元素的Array数组
scala> "hello world".split(" ") res0: Array[java.lang.String] = Array(hello, world) scala> "hello world".split(" ").foreach(println) hello world
对于下面的例子最好使用map方法调用trim去除左右两边的空格
scala> val s = "eggs, milk, butter, Coco Puffs" s: java.lang.String = eggs, milk, butter, Coco Puffs // 1st attempt scala> s.split(",") res0: Array[java.lang.String] = Array(eggs, " milk", " butter", " Coco Puffs") //此处引号的存在是因为空格的存在,所以必须用引号指出来 ---------正确姿势如下 // 2nd attempt, cleaned up scala> s.split(",").map(_.trim) res1: Array[java.lang.String] = Array(eggs, milk, butter, Coco Puffs)
匹配空白字符作为分隔符
scala> "hello world, this is Al".split("\\s+") //正则表达,见下 res0: Array[java.lang.String] = Array(hello, world,, this, is, Al)
split方法有些版本来自Java中String类,有的来自Scala中StringLike类,比如用字符串表示来自String,用字符表示来自StringLike
// split with a String argument scala> "hello world".split(" ") res0: Array[java.lang.String] = Array(hello, world) // split with a Char argument scala> "hello world".split(' ') res1: Array[String] = Array(hello, world)
正则表达\s+详解
正则表达式中\s匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[ \f\n\r\t\v]
\f -> 匹配一个换页 \n -> 匹配一个换行符 \r -> 匹配一个回车符 \t -> 匹配一个制表符 \v -> 匹配一个垂直制表符
- 而“\s+”则表示匹配任意多个上面的字符。另因为反斜杠在Java里是转义字符,所以在Java里,我们要这么用“\s+”.
1.4 在字符串中插入变量
1.4.1 在字符串中使用变量
2.10开始,Scala通过字符串插值可以有Perl,PHP,Puby语言一样的效果。如下需要字母 s 在字符串之前,字符串包含变量,变量前用 $ 符表示
scala> val name = "Fred" name: String = Fred scala> val age = 33 age: Int = 33 scala> val weight = 200.00 weight: Double = 200.0 scala> println(s"$name is $age years old, and weights $weight pounds.") Fred is 33 years old, and weights 200.0 pounds.
当字母 s 在字符串之前时,就创建了一个可处理的字符串文本。Scala中规定,当字母 s 出现在任何字符串之前都允许直接在字符串中使用变量。
1.4.2 在字符串中使用表达式
通过通过${}在字符串中插入算术表达式
//算术表达式 scala> println(s"Age next year: ${age + 1}") Age next year: 34 //相等表达式 scala> println(s"You are 33 years old: ${age == 33}") You are 33 years old: true
当打印对象的字段时需要用大括号包裹
//正确方式 scala> case class Student(name: String, score: Int) defined class Student scala> val hannah = Student("Hannah", 95) hannah: Student = Student(Hannah,95) scala> println(s"${hannah.name} has a score of ${hannah.score}") Hannah has a score of 95 //错误方式,此处是调用类的toString方法输出hannah变量 scala> println(s"$hannah.name has a score of $hannah.score") Student(Hannah,95).name has a score of Student(Hannah,95).score
1.4.3 字母s是一个方法
- 字母s是一个方法,尽管看起来比直接在字符串中插入变量要麻烦一点,但是它至少有以下两个优点:
- Scala提供了更多现成的插补函数
- 可以自定义插补函数
1.4.4 插补器f(使用printf格式),可以格式化输出值
输出两个小数位数
scala> println(f"$name is $age years old, and weighs $weight%.2f pounds.") Fred is 33 years old, and weighs 200.00 pounds.
完全去掉小数位
scala> println(f"$name is $age years old, and weighs $weight%.0f pounds.") Fred is 33 years old, and weighs 200 pounds.
把格式化的结果插补给另一个变量,如同在其他语言中调用sprintf一样(sprintf:字符串格式化命令,主要功能是把格式化的数据写入某个字符串中, sprintf函数的功能与printf函数的功能基本一样,只是它把结果输出到指定的字符串中了)
scala> val out = f"$name, you weigh $weight%.0f pounds." out: String = Fred, you weigh 200 pounds.
1.4.5 插补器raw
用于显示字符串中所有文本,原封不动的显示出来
scala> "foo\nbar" res0: String = foo bar scala> s"foo\nbar" res1: String = foo bar scala> raw"foo\nbar" res1: String = foo\nbar
当想要避免如\n转换成换行符情况的字符序列时将非常有用
1.4.6 自定义插补器
- 比较复杂,以后回顾看以下官方文档
- 字符串插补器在Scala2.10时对模式匹配语句不起作用,此功能计划在2.11上
1.4.7 2.10版本之前解决办法
如果因为某些原因需要使用2.10之前的版本,可以用format方法作用在字符串上,如下
scala> val name = "Fred" name: java.lang.String = Fred scala> val age = 33 age: Int = 33 scala> val s = "%s is %d years old".format(name, age) s: String = Fred is 33 years old scala> println("%s is %d years old".format(name, age)) Fred is 33 years old
和字符串插补器一样,这种方法也可以使用在任何需要格式化字符串的地方,比如toString方法
override def toString: String = "%s %s, age %d".format(firstName, lastName, age)
无论使用哪种方法,都可以使用printf说明符格式化变量。以下是常用格式符
格式符 描述 %c 字符型 %d 十进制整数 Decimal number (integer, base 10) %e 浮点型指数 %f 浮点数 %i 十进制整数 Integer (base 10) %o 八进制整数 %s 字符串 %u 十进制无符号整数 %x 十六进制整数 %% 打印百分比字符 \% 打印百分比字符
查看更多
更多printf格式符 format specifiers and examples
java中更多例子和细节 Oracle Formatter page
官方文档 The official Scala String Interpolation documentation