What is the advantage of using scala pattern matching instead of java switch case?

I'd first like to note that you don't use pattern matching "instead" of switch statements. Scala doesn't have switch statements, what it does have is match blocks, with cases inside that superficially look very similar to a switch statement.

Match blocks with pattern matching does everything that switch does, and much more.

A) It's not restricted to just primitives and other types that Oracle have chosen to "bless" in the language spec (Strings and Enums). If you want to match on your own types, go right ahead!

B) Pattern matching can also extract. For example, with a tuple:

val tup = ("hello world", 42)
tup match {
  case (s,i) =>
    println("the string was " + s)
    println("the number was " + i
}

With a list:

val xs = List(1,2,3,4,5,6)
xs match {
  case h :: t =>
    // h is the head: 1
    // t is the tail: 2,3,4,5,6
    // The :: above is also an example of matching with an INFIX TYPE
}

With a case class

case class Person(name: String, age: Int)
val p = Person("John Doe", 42)
p match {
  case Person(name, 42) =>
    //only extracting the name here, the match would fail if the age wasn't 42
    println(name)
}

C) pattern matching can be used in value assignment and for-comprehensions, not just in match blocks:

val tup = (19,73)

val (a,b) = tup

for((a,b) <- Some(tup)) yield a+b // Some(92)

D) match blocks are expressions, not statements

This means that they evaluate to the body of whichever case was matched, instead of acting entirely through side-effects. This is crucial for functional programming!

val result = tup match { case (a,b) => a + b }

Somehow my edit/addition to @KevinWright answer got thrown away, so I'll add it here as one more nice pattern matching feature...

F) Compiler exhaustiveness check of cases.

If there exists a value matching against which will not be covered by existing cases compiler will warn you about it. This is a very nice feature of the language because if you don't ignore these compiler warnings you won't catch such runtime exceptions or come across a case you didn't think of. If you still run the application and ignore the warning you will get a nice descriptive exception if your value does not match any cases. Here is an illustration:

scala> def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) }
<console>:7: warning: match may not be exhaustive.
It would fail on the following input: Nil
       def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) }
                                          ^
badMatch: (l: List[Int])Unit

scala> badMatch(List(1, 2))
1

scala> badMatch(Nil)
scala.MatchError: List() (of class scala.collection.immutable.Nil$)

I prefer to get an exception in this case because it will fail loud and clear, and usually early instead of executing unexpected branches of logic.

If you use if you would have to use else, and if you use Java switch you would have to have default case to cover all cases. But notice the difference: Scala compiler knows that your empty list is different from non-empty list in this case, or in more broad sense you define the granularity of matches. You could match lists with 1 or 2 elements and ignore the rest, or use any other much more complex patterns without having to worry if you managed to cover all cases.

In short as you use complex extraction and matching logic compiler will make sure you didn't miss any cases. There is nothing similar in Java unless you use a default case like default or else.


pattern matching is not somehow an alternative of switch statement, I consider it to be another way of doing dynamic dispatch in oop. They try to do the same thing: calling a different version of the function based on the dynamic type of the arguments