Scala Strings
Strings are one of the most commonly used data types in programming. Strings in Scala are based on Java's String class, but provide more convenient operation methods and syntactic sugar.
String Basics
String Creation
scala
object StringCreation {
def main(args: Array[String]): Unit = {
// Basic string creation
val str1 = "Hello, World!"
val str2 = new String("Hello, World!")
// Empty strings
val emptyStr1 = ""
val emptyStr2 = String.empty
// Create from character array
val charArray = Array('H', 'e', 'l', 'l', 'o')
val str3 = new String(charArray)
println(str1)
println(str2)
println(s"Empty string length: ${emptyStr1.length}")
println(str3)
// String comparison
println(s"str1 == str2: ${str1 == str2}") // true (content comparison)
println(s"str1 eq str2: ${str1 eq str2}") // false (reference comparison)
}
}String Literals
scala
object StringLiterals {
def main(args: Array[String]): Unit = {
// Regular strings
val normal = "This is a regular string"
// Strings with escape characters
val escaped = "First line\nSecond line\tTabbed text\\Backslash\\""
// Raw strings (triple quotes)
val raw = """This is a raw string
|Can contain newlines
|and "quotes" without escaping
|Backslash \ also not needs escaping""".stripMargin
// Multi-line strings
val multiline =
"""SELECT name, age
|FROM users
|WHERE age > 18
|ORDER BY name""".stripMargin
println(normal)
println(escaped)
println(raw)
println(multiline)
}
}String Interpolation
s Interpolator
scala
object SInterpolation {
def main(args: Array[String]): Unit = {
val name = "Alice"
val age = 25
val height = 1.68
// s interpolator - basic usage
val greeting = s"Hello, my name is $name"
val info = s"I am $age years old and ${height}m tall"
// Expression interpolation
val calculation = s"Next year I will be ${age + 1} years old"
val formatted = s"Height in cm: ${height * 100}"
println(greeting)
println(info)
println(calculation)
println(formatted)
// Complex expressions
val numbers = List(1, 2, 3, 4, 5)
val summary = s"Numbers: ${numbers.mkString(", ")}, Sum: ${numbers.sum}"
println(summary)
}
}f Interpolator (Formatting)
scala
object FInterpolation {
def main(args: Array[String]): Unit = {
val name = "Bob"
val score = 85.6789
val percentage = 0.856
// f interpolator - formatted output
val formatted1 = f"$name scored $score%.2f points"
val formatted2 = f"Percentage: $percentage%.1%%" // %% represents % character
// Number formatting
val pi = 3.14159265359
val formatted3 = f"Pi to 3 decimal places: $pi%.3f"
val formatted4 = f"Pi in scientific notation: $pi%.2e"
// String formatting
val formatted5 = f"Name: $name%10s" // Right aligned, width 10
val formatted6 = f"Name: $name%-10s|" // Left aligned, width 10
println(formatted1)
println(formatted2)
println(formatted3)
println(formatted4)
println(formatted5)
println(formatted6)
}
}raw Interpolator
scala
object RawInterpolation {
def main(args: Array[String]): Unit = {
val path = "C:\\Users\\Alice\\Documents"
// raw interpolator - does not process escape characters
val rawString = raw"Path: $path\nThis \t will \\ not \\ be \\ escaped"
val normalString = s"Path: $path\nThis \t will \\ be \\ escaped"
println("Raw interpolation:")
println(rawString)
println("\nNormal interpolation:")
println(normalString)
// Useful in regular expressions
val regex = raw"\d{3}-\d{2}-\d{4}" // No need to double escape
println(s"Regex pattern: $regex")
}
}String Operations
Basic Operations
scala
object BasicStringOperations {
def main(args: Array[String]): Unit = {
val str = "Hello, Scala World!"
// Length and index
println(s"Length: ${str.length}")
println(s"First character: ${str(0)}")
println(s"Last character: ${str(str.length - 1)}")
// Substrings
println(s"Substring(0, 5): ${str.substring(0, 5)}")
println(s"Substring(7): ${str.substring(7)}")
// Find operations
println(s"Index of 'Scala': ${str.indexOf("Scala")}")
println(s"Last index of 'l': ${str.lastIndexOf('l')}")
println(s"Contains 'World': ${str.contains("World")}")
// Case conversions
println(s"Uppercase: ${str.toUpperCase}")
println(s"Lowercase: ${str.toLowerCase}")
// Trim whitespace
val paddedStr = " Hello, World! "
println(s"Trimmed: '${paddedStr.trim}'")
// Replacement
println(s"Replace 'World' with 'Scala': ${str.replace("World", "Scala")}")
println(s"Replace first 'l' with 'L': ${str.replaceFirst("l", "L")}")
}
}String Splitting and Joining
scala
object StringSplitJoin {
def main(args: Array[String]): Unit = {
val csv = "apple,banana,orange,grape"
val sentence = "The quick brown fox jumps over lazy dog"
// Split strings
val fruits = csv.split(",")
val words = sentence.split(" ")
println("Fruits:")
fruits.foreach(println)
println("\nWords:")
words.foreach(println)
// Join strings
val joined1 = fruits.mkString(" | ")
val joined2 = words.mkString("[", ", ", "]")
println(s"\nJoined fruits: $joined1")
println(s"Joined words: $joined2")
// Use separator
val numbers = Array(1, 2, 3, 4, 5)
val numberString = numbers.mkString(", ")
println(s"Numbers: $numberString")
// String builder
val sb = new StringBuilder()
sb.append("Hello")
sb.append(", ")
sb.append("World")
sb.append("!")
println(s"StringBuilder result: ${sb.toString}")
}
}String Matching and Regular Expressions
scala
import scala.util.matching.Regex
object StringMatching {
def main(args: Array[String]): Unit = {
val text = "My phone number is 123-456-7890 and email is user@example.com"
// Regular expressions
val phonePattern: Regex = """\d{3}-\d{3}-\d{4}""".r
val emailPattern = """[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}""".r
val datePattern = """\d{4}-\d{2}-\d{2}""".r
// Find matches
val phoneMatch = phonePattern.findFirstIn(text)
val emailMatch = emailPattern.findFirstIn(text)
println(s"Phone: ${phoneMatch.getOrElse("Not found")}")
println(s"Email: ${emailMatch.getOrElse("Not found")}")
// Find all matches
val numbers = """\d+""".r
val allNumbers = numbers.findAllIn("There are 123 apples and 456 oranges").toList
println(s"All numbers: $allNumbers")
// Replace matches
val censored = phonePattern.replaceAllIn(text, "XXX-XXX-XXXX")
println(s"Censored: $censored")
// Pattern matching
val input = "user@domain.com"
input match {
case emailPattern() => println("Valid email format")
case _ => println("Invalid email format")
}
// Extract groups
val namePattern = """(\w+)\s+(\w+)""".r
val fullName = "John Doe"
fullName match {
case namePattern(first, last) =>
println(s"First name: $first, Last name: $last")
case _ =>
println("Name pattern not matched")
}
}
}String Advanced Operations
String Conversion
scala
object StringConversion {
def main(args: Array[String]): Unit = {
// String to numbers
val numberStr = "123"
val floatStr = "3.14"
val boolStr = "true"
val intValue = numberStr.toInt
val floatValue = floatStr.toFloat
val boolValue = boolStr.toBoolean
println(s"String to Int: $intValue")
println(s"String to Float: $floatValue")
println(s"String to Boolean: $boolValue")
// Safe conversion
def safeToInt(str: String): Option[Int] = {
try {
Some(str.toInt)
} catch {
case _: NumberFormatException => None
}
}
println(s"Safe conversion '123': ${safeToInt("123")}")
println(s"Safe conversion 'abc': ${safeToInt("abc")}")
// String to collections
val str = "Hello"
val charList = str.toList
val charArray = str.toCharArray
println(s"String to List: $charList")
println(s"String to Array: ${charArray.mkString("[", ", ", "]")}")
// Numbers to strings
val num = 42
val numStr1 = num.toString
val numStr2 = String.valueOf(num)
println(s"Number to String: $numStr1")
println(s"Using valueOf: $numStr2")
}
}String Formatting
scala
object StringFormatting {
def main(args: Array[String]): Unit = {
val name = "Alice"
val age = 30
val salary = 50000.0
// Use format method
val formatted1 = "Name: %s, Age: %d, Salary: %.2f".format(name, age, salary)
println(formatted1)
// Positional arguments
val formatted2 = "Hello %1$s, you are %2$d years old. Nice to meet you, %1$s!".format(name, age)
println(formatted2)
// Number formatting
val pi = 3.14159265359
println(f"Pi: $pi%8.3f") // Width 8, 3 decimal places
println(f"Pi: $pi%08.3f") // Pad with zeros
println(f"Pi: $pi%-8.3f") // Left align
// Percentage formatting
val percentage = 0.75
println(f"Success rate: $percentage%.1%%")
// Scientific notation
val bigNumber = 1234567.89
println(f"Big number: $bigNumber%.2e")
// Hexadecimal
val number = 255
println(f"Hex: $number%x")
println(f"Hex (uppercase): $number%X")
}
}String Performance Optimization
scala
object StringPerformance {
def main(args: Array[String]): Unit = {
// String concatenation performance comparison
def concatenateWithPlus(n: Int): String = {
var result = ""
for (i <- 1 to n) {
result += s"Item $i "
}
result
}
def concatenateWithBuilder(n: Int): String = {
val sb = new StringBuilder()
for (i <- 1 to n) {
sb.append(s"Item $i ")
}
sb.toString
}
def concatenateWithMkString(n: Int): String = {
(1 to n).map(i => s"Item $i").mkString(" ")
}
// Performance test
val n = 1000
val start1 = System.currentTimeMillis()
val result1 = concatenateWithPlus(n)
val time1 = System.currentTimeMillis() - start1
val start2 = System.currentTimeMillis()
val result2 = concatenateWithBuilder(n)
val time2 = System.currentTimeMillis() - start2
val start3 = System.currentTimeMillis()
val result3 = concatenateWithMkString(n)
val time3 = System.currentTimeMillis() - start3
println(s"String concatenation with +: ${time1}ms")
println(s"StringBuilder: ${time2}ms")
println(s"mkString: ${time3}ms")
// String pool
val str1 = "Hello"
val str2 = "Hello"
val str3 = new String("Hello")
println(s"str1 eq str2: ${str1 eq str2}") // true (string pool)
println(s"str1 eq str3: ${str1 eq str3}") // false (new object)
println(s"str1 == str3: ${str1 == str3}") // true (same content)
}
}Practical Application Examples
Text Processing Tool
scala
object TextProcessor {
def wordCount(text: String): Map[String, Int] = {
text.toLowerCase
.replaceAll("[^a-zA-Z\\s]", "") // Remove punctuation
.split("\\s+") // Split by whitespace
.filter(_.nonEmpty) // Filter empty strings
.groupBy(identity) // Group by word
.view.mapValues(_.length).toMap // Count occurrences of each word
}
def reverseWords(text: String): String = {
text.split(" ").map(_.reverse).mkString(" ")
}
def isPalindrome(text: String): Boolean = {
val cleaned = text.toLowerCase.replaceAll("[^a-zA-Z0-9]", "")
cleaned == cleaned.reverse
}
def capitalizeWords(text: String): String = {
text.split(" ").map(word =>
if (word.nonEmpty) word.head.toUpper + word.tail.toLowerCase
else word
).mkString(" ")
}
def main(args: Array[String]): Unit = {
val text = "Hello world! This is a sample text for testing. Hello appears twice."
println("Original:")
println(text)
println("\nWord count:")
wordCount(text).foreach { case (word, count) =>
println(s"$word: $count")
}
println(s"\nReverse words: ${reverseWords(text)}")
val palindromes = List("A man a plan a canal Panama", "race a car", "hello")
println("\nPalindrome test:")
palindromes.foreach { str =>
println(s"'$str' is palindrome: ${isPalindrome(str)}")
}
println(s"\nCapitalize words: ${capitalizeWords("hello world from scala")}")
}
}Template Engine
scala
object SimpleTemplateEngine {
def render(template: String, variables: Map[String, String]): String = {
variables.foldLeft(template) { case (result, (key, value)) =>
result.replace(s"{{$key}}", value)
}
}
def renderWithDefaults(template: String, variables: Map[String, String], defaults: Map[String, String] = Map.empty): String = {
val allVars = defaults ++ variables
val variablePattern = """\{\{(\w+)\}\}""".r
variablePattern.replaceAllIn(template, m => {
val varName = m.group(1)
allVars.getOrElse(varName, s"{{$varName}}") // Keep unfound variables
})
}
def main(args: Array[String]): Unit = {
val template = "Hello {{name}}, welcome to {{site}}! Your role is {{role}}."
val variables = Map(
"name" -> "Alice",
"site" -> "Scala Tutorial"
)
val defaults = Map(
"role" -> "student"
)
val result1 = render(template, variables ++ defaults)
val result2 = renderWithDefaults(template, variables, defaults)
println("Simple render:")
println(result1)
println("\nRender with defaults:")
println(result2)
// Missing variables case
val incompleteVars = Map("name" -> "Bob")
val result3 = renderWithDefaults(template, incompleteVars, defaults)
println("\nMissing variables render:")
println(result3)
}
}Config File Parser
scala
object ConfigParser {
case class Config(properties: Map[String, String]) {
def getString(key: String): Option[String] = properties.get(key)
def getInt(key: String): Option[Int] = properties.get(key).flatMap(v =>
try Some(v.toInt) catch { case _: NumberFormatException => None }
)
def getBoolean(key: String): Option[Boolean] = properties.get(key).map(_.toLowerCase == "true")
}
def parseConfig(configText: String): Config = {
val properties = configText
.split("\n")
.map(_.trim)
.filter(line => line.nonEmpty && !line.startsWith("#")) // Filter empty lines and comments
.flatMap { line =>
line.split("=", 2) match {
case Array(key, value) => Some(key.trim -> value.trim)
case _ => None
}
}.toMap
Config(properties)
}
def main(args: Array[String]): Unit = {
val configText =
"""# Database configuration
|host=localhost
|port=5432
|database=myapp
|username=admin
|password=secret123
|ssl_enabled=true
|connection_timeout=30
|
|# Application settings
|debug_mode=false
|max_users=1000""".stripMargin
val config = parseConfig(configText)
println("Configuration parse result:")
println(s"Host: ${config.getString("host").getOrElse("unknown")}")
println(s"Port: ${config.getInt("port").getOrElse(0)}")
println(s"SSL Enabled: ${config.getBoolean("ssl_enabled").getOrElse(false)}")
println(s"Max Users: ${config.getInt("max_users").getOrElse(100)}")
println(s"Debug Mode: ${config.getBoolean("debug_mode").getOrElse(false)}")
}
}Best Practices
- Use string interpolation: Prioritize
s"$variable"instead of string concatenation - Choose the right interpolator:
sfor general interpolation,ffor formatting,rawfor raw strings - Performance considerations: Use
StringBuilderor functional methods for extensive string operations - Avoid null pointers: Use
Optionto handle potentially null strings - Regular expressions: Use regular expressions for complex string matching
- Immutability: Strings are immutable, operations create new strings
Mastering string operations is fundamental to Scala programming, these techniques will be frequently used in actual development.