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. 
Back to top

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.
Back to top

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.

Back to top

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.

Back to top

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)
Back to top

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.

Back to top

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.

Back to top

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)
Back to top

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. ;)

Back to top

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.

Back to top

"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.

Back to top

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.

Back to top

Comments

Permalink

Nice Article. A few bugs:
- Under, "Method to double every element in a collection" - Java version should be results.add(i*2) not results.add(i)
- The Scala method can also be written as nums.map(2*) (I get a warning in the REPL with this though.)
- I also think it will be nice to show the full version when using map. So, nums.map(x => x*2)
Please keep the tuts coming. I love your blog!
Cheers, Fayi

Permalink

To create a list, you can also do:

val names = "Fred" :: "Barney" :: "Wilma" :: Nil

Nice article, i totally agree with you !
Nevertheless, some java example can be simplified :

Since java 7, diamond operator make this possible :
- Before : List strings = new LinkedList(); // java
- After : List strings = new LinkedList<>(); // java

And since java 5, vararg make this possible
- Before : List names = Arrays.asList(new String[]{"Fred", "Barney", "Wilma"}); (the closing curly brace is missing in your example)
- After : List names = Arrays.asList("Fred", "Barney", "Wilma");

But the code is still more verbose than the Scala equivalent :)

Thanks Yann. I updated the Java examples based on your suggestions. I haven't used Java in a while now, but I think you still need to declare something like List<String> on the left side of the expression to declare the type, which makes it equivalent to what Scala does, so I added that in. Thanks!
Permalink

Very nice article. It really shows why Scala is a better Java.

What I want to do some day, and you would be in the position to do as well, is to write an article on how Scala is a better Ruby.

A Ruby developer, if only looking at the Scala code, might be left wondering: "what's so special about Scala? Ruby can do the same, and I have to type even less".

In my opinion and experience, what Scala brings on top of Ruby is:
* more readability, by being able to read the type declarations (parameters, return types, etc.)
* unmatched IDE support for refactoring, compiler feedback, etc.

Ruby on the other hand beats Scala on other things like:
* interactivity (being more able to interact, debug and change a running system)
* faster development cycles (Scala compiler is dog slow, Ruby is immediate)
* metaprogramming is easier
* scripting

My preference for medium to large projects is still Scala anyway.

Hi Alvin,

I fell into the trap of escape characters :
Obviously, it should read

- Before : List<String> strings = new LinkedList<String>(); // java
- After : List<String> strings = new LinkedList<>(); // java

Permalink

Scala isn't limited to FP as you pointed, and programmers should be aware that it can be used in may other ways. However, I disagree with the "better Java" rhetoric. Although it compiles for the JVM (other targets such as .net are work in progress), its syntax has been designed from scratch in order to reach its objectives (concise, expressive, and yet statically typed etc. as you explained well). The counter-example would be Groovy, whose syntax is a variant of Java's. I do prefer Scala, I find it more productive, than Groovy or Java, but it's quite different. Like C isn't a better Pascal. As a side note, the learning curve can be steep, well if people want to learn all the powerful features, but I believe it's worth the effort. I didn't want to undertake the effort at first, went with Groovy, but didn't like the dynamic approach (getting most errors at run time and there was no static compilation at the time). So eventually I learned Scala and I am very happy I did, because I got rid of most of the syntactic bloat/frustration that prevented me to transform my ideas into code in a timely manner.

Add new comment

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.