Using Scala as a “better Java”

A lot of people want to sell Scala as a functional programming (FP) language. That's fine, it certainly is, and FP has many benefits. But when I first started working with Scala I was just looking for a "better Java".

Personally, I grew tired of Java's verbosity. Ruby showed us a different way, and I loved it, but ... after a while I felt like many of my unit tests in Ruby wouldn't be necessary if the language had static types. I wished for a concise Ruby-like language with static types.

And then in a crazy event, I stumbled onto Scala in a little used bookstore in Alaska. In short, here's what I've learned about Scala:

So you get all these features, and all the benefits of the JVM, including the use of all the Java libraries out there.

  • It's more concise (but not terse).
  • It's expressive.
  • It's statically typed, but it feels dynamic.
  • It has traits.
  • It compiles down to Java class files which you can package as normal Java jar files.
  • It feels like Ruby, but it's statically typed, so I don't have to write type-related unit tests. 

Examples

So far all I've said is "blah blah blah", so let's communicate with some source code examples to show the differences between the languages. But first, two notes:

  1. This article is a work in progress. I just wanted to get it started out here today. I'll add more examples as I have time.
  2. I haven't compiled any of this code, so I may have made some syntax mistakes here and there. But hopefully the code is generally in the ballpark.

A class to launch your application

To get warmed up, let's look at how to create a class to launch an application. First, here's a Java class with a main method:

public class Foo {
  public static void main (String[] args) {
    // code
  }
}

Next, here's Scala:

object Foo extends App {
  // code
}

Nothing major, but a little starter to get my juices flowing.

Types

Let's look at defining a few types. Here's a String in Java:

String name = "Alvin";

Here's the same string variable in Scala:

val name = "Alvin"

Using the Person class defined a few paragraphs below, here's a new Person instance in Java:

Person p = new Person("Al", "Pacino");

Here's how you do it in Scala:

val p = Person("Al", "Pacino")

This is one of the ways Scala feels like a dynamically-typed language, though it is static.

Collections and loops

Next, let's look at a few ways to declare collections. This is how you'd declare a mutable collection of strings in each language:

List<String> strings = new LinkedList<>();  // java
val strings = new ArrayBuffer[String]()     // scala

If you want to populate a list of strings when you create it, I think this is the correct approach in Java:

List<String> names = Arrays.asList("Fred", "Barney", "Wilma");

In Scala you'd do it like this:

val names = List("Fred", "Barney", "Wilma")

Here's an example of creating an integer array in Java and then printing each element in the collection:

int[] nums = {1, 2, 3};
for(int i: numbers) {
  System.out.print(i);
}

Here's the same example in Scala:

val nums = Array(1,2,3)
nums.foreach(println)

You can also shorten that example to this:

Array(1,2,3).foreach(println)

Defining a class

One area where Scala is dramatically better than Java is in the definition of classes. Here's a declaration of a Person class with just two constructor arguments, written in Java:

// java
public class Person {

  private firstName;
  private lastName;
  
  public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  
  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }
  
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

}

Here's basically the same class in Scala:

// scala
case class Person(var firstName: String, var lastName: String)

The Scala class also has other benefits, but for now we'll just think of it as being the equal of that Java class.

Method to double an int

Here are two simple methods to double an integer. First, the Java version:

public int double(int i) {
  return i * 2;
}

Next, the Scala version:

def double(i: Int) = i * 2

I'll show more/better examples over time, but the point I want to make is that many methods in Scala can be boiled down to one or two lines of code.

Method to double every element in a collection

A method to double every element in a collection demonstrates more differences between Java and Scala. I believe this is a concise Java method:

// java
public List<Integer> double(List<Integer> nums) {
  List<Integer> results = new ArrayList<Integer>();  
  for (int i: nums) {
    results.add(i*2);
  }
  return results;
}

Here's a Scala method that does the same thing:

// scala (1)
def double(nums: List[Int]) = for(i <- nums) yield i*2

You can also annotate the return type of the method, if you prefer:

// scala (1)
def double(nums: List[Int]):List[Int] = for(i <- nums) yield i*2

Once you get comfortable with the Scala collections map method and where the underscore character can be used, you can make your method more concise, if you prefer:

// scala (2)
def double(nums: List[Int]) = nums.map(_ * 2)

If you don't like the underscore approach, this works too:

// scala (2)
def double(nums: List[Int]) = nums.map(x => x * 2)

Loops and filters

Manipulating collections is a wonderful strength of Scala. Say you want to create a new collection that has each element as the original collection, but with all the elements in uppercase. Here's one way to do this in Scala:

val fruits = Seq("apple", "banana", "cherry", "mango", "orange", "tomato")
val uppercaseFruits = fruits.map(_.toUpperCase)

The variable uppercaseFruits now has the same list of elements, but they're all uppercase. No big deal, but suppose you don't think a tomato is a fruit, what to do then? In Scala you can easily filter it out:

val uppercaseFruits = fruits.filter(_ != "tomato").map(_.toUpperCase)

These days I can easily read that statement, but if you don't like it, you can achieve the same result with a for loop:

val uppercaseFruits = for {
  f <- fruits
  if f != "tomato"
} yield f

A great strength of Scala is that there's more than one way to achieve the same result, so if you prefer the for loop, no worries, go with what you're comfortable with.

(I didn't show these examples in Java; I'm leaving that as an exercise for the reader. ;)

Scala's higher-order functions

I apologize, I don't remember where I got the next slide from, but it shows a terrific example of the verbosity of Java that was driving me crazy, and how you can solve the same problem very simply in Scala with a higher-order function:

While the Java code requires a large amount of boilerplate code to get around a deficiency in the language, the Scala code solves the same problem by passing an anonymous function as a parameter to another function.

"House rules"

One complaint I've heard about with Scala is that it can get more complicated, especially with some of the things you can do with the underscore character. To that I say hogwash. If you don't like a feature, don't use it!

Years ago when I was learning Function Point Analysis (FPA), I was taught about a concept named "house rules". In FPA this meant that if you didn't like the industry-standard rules, screw them, and use your own "in-house" rules. As long as everyone used the same rules at your company, i.e., you were consistent, you could still count "points" to determine how large your application is. You just couldn't compare your points to the industry standard.

You can do the same thing with Scala. If your team isn't comfortable with a feature during Month 1 of adopting Scala, no worries, don't use it! Once you later grok how it works, add it to your "house rules" at that time.

P.S. - If you've heard the complaint that Scala is too complicated, and that argument is based on the fact that some Scala developer created a library with an insane API, don't throw the baby out with the bath water. Just because a developer has poor taste when it comes to designing an API, it doesn't mean the language is bad. Languages like C and C++ also give you enough power to do really stupid things, but that doesn't make them bad languages.

More examples to come

As mentioned, I'm just getting started on this article. There are many other benefits to demonstrate where Scala is "a better Java", including:

  • Methods are consistently more concise, and still as readable. I'll show better examples of this.
  • Case statements have much more power (use integers, strings, objects, etc.)
  • Traits
  • Using Scala as a scripting language
  • String interpolation
  • Besides designing applications, much of our life involves working with collections. Scala's collections kick ass (it just takes a little time to see that). I may share more examples of this, but there are a ton of them on this site already. Just search for things like scala map, scala flatMap, scala list, or scroll through over 150 Scala tutorials.

With the Akka library both languages can use actors, so I won't say that's a benefit to Scala, although your actor code will be more concise with Scala.

That's it for today, hopefully a decent start. I'll include more examples as I have time.