95

I need some code samples (and I also really curious about them) of Scala and Java code which show that Scala code is more simple and concise then code written in Java (of course both samples should solve the same problem).

If there is only Scala sample with comment like "this is abstract factory in Scala, in Java it will look much more cumbersome" then this is also acceptable.

Thanks!

I like most of all accepted and this answers

Community
  • 1
  • 1
Roman
  • 64,384
  • 92
  • 238
  • 332
  • 3
    With a little leg-work, you might find plenty of samples at http://rosettacode.org – nicerobot Jun 01 '10 at 22:32
  • 4
    How can there be one correct answer in this kind of question? – polygenelubricants Jun 02 '10 at 11:12
  • @polygenelubricants: and what you suggest? – Roman Jun 02 '10 at 11:15
  • Where's the cw police when needed? – OscarRyz Jun 02 '10 at 21:18
  • @closer: you say 'subjective and argumentative' as if it's something bad. btw, it's subjective but not argumentative. – Roman Jun 02 '10 at 22:02
  • @Oscar Reyes: I don't actually think that this question is a comminity wiki. There is no correspondent kind of question at SO now. It's a usual question but with multiple correct answers. Currently I see at least 2 correct answers. Even if I mark a question as *cw* I will not be able to mark out those 2 answers. So, the police has nothing to do here. – Roman Jun 02 '10 at 22:08
  • 10
    @Roman: We expect Scala to be more concise. It would be more interesting if you could find something that was more concisely expressed in Java than in Scala. – Randall Schulz Jun 03 '10 at 16:41
  • 1
    @Randall Schulz: everyone knows that Scala is more concise, but sometimes, in academic purpose, we need a proof with examples and background theory. – Roman Jun 04 '10 at 12:46
  • @Roman: The SO FAQ says "Avoid asking questions that are subjective, argumentative, or require extended discussion." Not that it says "or" rather than "and." The close box description for "subjective and argumentative" also states "It's impossible to objectively answer this question; questions of this type are too **open ended** and usually lead to confrontation and argument." (emphasis mine) – Powerlord Jun 04 '10 at 17:59
  • @R. Bemrose: nothing's pefrect. And SO rules only confirm this state. Subjective and argumentative is a question like "what is better, java or C#?". This question involves discussion and different but not controversial opinions. SO has possibility to discuss **too open ended** questions and it definitely should be used, but this question is not the one. There is definitely a final number of pretty-looking correct answers exist, I thinkg about 10 or even less. – Roman Jun 04 '10 at 19:27

18 Answers18

78

Let's improve stacker's example and use Scala's case classes:

case class Person(firstName: String, lastName: String)

The above Scala class contains all features of the below Java class, and some more - for example it supports pattern matching (which Java doesn't have). Scala 2.8 adds named and default arguments, which are used to generate a copy method for case classes, which gives the same ability as the with* methods of the following Java class.

public class Person implements Serializable {
    private final String firstName;
    private final String lastName;

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

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Person withFirstName(String firstName) {
        return new Person(firstName, lastName);
    }

    public Person withLastName(String lastName) {
        return new Person(firstName, lastName);
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Person person = (Person) o;
        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
            return false;
        }
        if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
            return false;
        }
        return true;
    }

    public int hashCode() {
        int result = firstName != null ? firstName.hashCode() : 0;
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        return result;
    }

    public String toString() {
        return "Person(" + firstName + "," + lastName + ")";
    }
}

Then, in usage we have (of course):

Person mr = new Person("Bob", "Dobbelina");
Person miss = new Person("Roberta", "MacSweeney");
Person mrs = miss.withLastName(mr.getLastName());

Against

val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)
Community
  • 1
  • 1
Esko Luontola
  • 73,184
  • 17
  • 117
  • 128
  • You have to be careful though - case classes inherit from `Product` and hence primitives will be boxed (in scala 2.7) or probably-boxed (2.8 using specialization) – oxbow_lakes Jun 03 '10 at 10:38
  • 2
    In 2.7.x and 2.8.0 the only boxing is in `productElements` and `unapply`, not in the constructor, field, or accessor: http://gist.github.com/424375 – retronym Jun 03 '10 at 19:58
  • 2
    Encourages all sorts of getter/setter badness. Setters should only be added with extreme reluctance, getters should be only added if necessary. Good example of how adding "Simplicity" leads to bad habits. – Bill K Jul 02 '10 at 21:37
  • 7
    @Bill K: OK, then we will have `case class Person(val firstName: String, val lastName: String)` So what? Making that thing private would be possible too, but doesn't make any sense, because of unapply etc. – soc Jul 16 '10 at 19:49
  • How to make the `firstName and lastName` in Scala as Private ? – Siva Aug 28 '13 at 07:14
  • 1
    @shiva `case class Person(private val firstName: String)`, but you shouldn't be using case classes then. Instead do `class Person(firstName: String)` and `firstName` is private by default. – nilskp Sep 19 '13 at 17:12
  • will scala generate get* methods if I define `firstName and lastName` as private ? – Siva Sep 20 '13 at 12:30
  • 1
    @shiva No. The difference between `val` and `private val` is that whether the accessor methods, i.e. `firstName()` and `firstName(String)`, are public or private. In Scala fields are always private. For Scala to generate Java-style get/set methods (in addition to the Scala-style accessors), there is the `@BeanProperty` annotation. – Esko Luontola Sep 20 '13 at 14:32
  • @BillK also note that scala classes are immutable by default. If you look carefully, you see that Person does NOT have any setters -- just getters and copy (which produces a new person). – VasiliNovikov Dec 05 '13 at 05:40
  • @Vasya My real issue is--Why do we define an object with properties when we never do anything with them in code? If the objects job is simply to travel from a GUI to the DB, having an object with properties can ONLY add code (If you think about it, the ONLY info you NEED to get a "name" from a GUI form to the DB is the name of the field on the form and the table/field name in the DB (and maybe the name of a validator), zero code!--any code touching a specific property is boilerplate. You can solve this by annotating a plain data object, but then you still don't need getters. – Bill K Dec 05 '13 at 18:36
  • If you didn't allow setters and getters it would FORCE you to write your code better, accessing pure data as data (Programatically as fields based on data rarther than directly through redundant, meaningless copy&paste code). Also in "Real" classes with members that need to be manipulated you would have to do so from within the class itself (where it should be accessed) instead of in external code that needs to "Get" the data. (Sorry about the comment length restriction, but I don't know where else to put this--does SO have a linkable "Wiki" or blog for posting longer responses/concepts)? – Bill K Dec 05 '13 at 18:41
45

I found this one impressive

Java

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

Scala

class Person(val firstName: String, val lastName: String)

As well as these ones (sorry for not pasting, I didn't want to steal the code)

stacker
  • 68,052
  • 28
  • 140
  • 210
  • This scala code will not generate `getFirstName` and `getLastName` methods. You have to annotate the parameters with `scala.reflect.BeanProperty` annotation to do that. – Abhinav Sarkar Jun 01 '10 at 20:01
  • 7
    @abhin4v: Yes, but the code convention in Scala is to not have accessors prefixed with `get`. Idiomatic Java code is different from idiomatic Scala code. Sometimes the `is` prefix used for booleans. http://davetron5000.github.com/scala-style/naming_conventions/methods/accessors_mutators.html – Esko Luontola Jun 01 '10 at 20:40
  • 7
    You could make that a `case class` and get the `toString`, `equals` and `hashCode` for free (and you also don't have to make the arguments `val` explicitly): `case class Person(firstName: String, lastName: String)` – Jesper Jun 01 '10 at 20:50
  • @shiva, for `case class`, not for just `class`. – nilskp Sep 19 '13 at 17:13
23

Task: Write a program to index a list of keywords (like books).

Explanation:

  • Input: List<String>
  • Output: Map<Character, List<String>>
  • The key of map is 'A' to 'Z'
  • Each list in the map are sorted.

Java:

import java.util.*;

class Main {
  public static void main(String[] args) {
    List<String> keywords = Arrays.asList("Apple", "Ananas", "Mango", "Banana", "Beer"); 
    Map<Character, List<String>> result = new HashMap<Character, List<String>>(); 
    for(String k : keywords) {   
      char firstChar = k.charAt(0);     
      if(!result.containsKey(firstChar)) {     
        result.put(firstChar, new  ArrayList<String>());   
      }     
      result.get(firstChar).add(k); 
    } 
    for(List<String> list : result.values()) {   
      Collections.sort(list); 
    }
    System.out.println(result);         
  }
}

Scala:

object Main extends App {
  val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
  val result = keywords.sorted.groupBy(_.head)
  println(result)
}
Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
11

Task:

You have a list people of objects of class Person that has fields name and age. Your task is to sort this list first by name, and then by age.

Java 7:

Collections.sort(people, new Comparator<Person>() {
  public int compare(Person a, Person b) {
    return a.getName().compare(b.getName());
  }
});
Collections.sort(people, new Comparator<Person>() {
  public int compare(Person a, Person b) {
    return Integer.valueOf(a.getAge()).compare(b.getAge());
  }
});

Scala:

val sortedPeople = people.sortBy(p => (p.name, p.age))

Update

Since I wrote this answer, there has been quite some progress. The lambdas (and method references)have finally landed in Java, and they are taking the Java world by storm.

This is what the above code will look like with Java 8 (contributed by @fredoverflow):

people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));

While this code is almost as short, it does not work quite as elegantly as the Scala one.

In Scala solution, the Seq[A]#sortBy method accepts a function A => B where B is required to have an Ordering. Ordering is a type-class. Think best of both worlds: Like Comparable, it's implicit for the type in question, but like Comparator, it's extensible and can be added retrospectively to types that did not have it. Since Java lacks type-classes, it has to duplicate every such method, once for Comparable, then for Comparator. For example, see comparing and thenComparing here.

The type-classes allow one to write rules such as "If A has ordering and B has ordering, then their tuple (A, B) also has ordering". In code, that is:

implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl

That is how the sortBy in our code can compare by name and then by age. Those semantics will be encoded with the above "rule". A Scala programmer would intuitively expect this to work this way. No special purpose methods like comparing had to be added to Ordering.

Lambdas and method references are just a tip of an iceberg that is functional programming. :)

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
10

A map of actions to perform depending on a string.

Java 7:

// strategy pattern = syntactic cruft resulting from lack of closures
public interface Todo {   
  public void perform();
}

final Map<String, Todo> todos = new HashMap<String,Todo>();
todos.put("hi", new Todo() { 
    public void perform() { 
        System.out.println("Good morning!");
    } 
} );

final Todo todo = todos.get("hi");
if (todo != null)
    todo.perform();
else
    System.out.println("task not found");

Scala:

val todos = Map( "hi" -> { () => println("Good morning!") } )
val defaultFun = () => println("task not found")
todos.getOrElse("hi", defaultFun).apply()

And it's all done in the best possible taste!

Java 8:

Map<String, Runnable> todos = new HashMap<>();
todos.put("hi", () -> System.out.println("Good morning!"));
Runnable defaultFun = () -> System.out.println("task not found");
todos.getOrDefault("hi", defaultFun).run();
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
Ben Hardy
  • 1,739
  • 14
  • 16
10

Task:

You have got an XML file "company.xml" that looks like this:

<?xml version="1.0"?>
<company>
    <employee>
        <firstname>Tom</firstname>
        <lastname>Cruise</lastname>
    </employee>
    <employee>
        <firstname>Paul</firstname>
        <lastname>Enderson</lastname>
    </employee>
    <employee>
        <firstname>George</firstname>
        <lastname>Bush</lastname>
    </employee>
</company>

You have to read this file and print the firstName and lastName fields of all the employees.


Java: [ taken from here ]

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlReader {
  public static void main(String[] args) {   
    try {
      File file = new File("company.xml");
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(file);
      doc.getDocumentElement().normalize();
      NodeList nodeLst = doc.getElementsByTagName("employee");
      for (int s = 0; s < nodeLst.getLength(); s++) {  
        Node fstNode = nodeLst.item(s); 
        if (fstNode.getNodeType() == Node.ELEMENT_NODE) {         
          Element fstElmnt = (Element) fstNode;
          NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("firstname");
          Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
          NodeList fstNm = fstNmElmnt.getChildNodes();
          System.out.println("First Name: "  + ((Node) fstNm.item(0)).getNodeValue());
          NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("lastname");
          Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
          NodeList lstNm = lstNmElmnt.getChildNodes();
          System.out.println("Last Name: " + ((Node) lstNm.item(0)).getNodeValue());
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}



Scala: [ taken from here, slide #19 ]

import xml.XML

object XmlReader {
  def main(args: Array[String]): Unit = {
    XML.loadFile("company.xml") match {
      case <employee> { employees @ _* } </employee> => {
        for(e <- employees) {
          println("First Name: " + (e \ "firstname").text)
          println("Last Name: " + (e \ "lastname").text)
        } 
      }
    }
  }
}

[ EDIT by Bill; Check comments for the discussion ] --

Hmm, how to do it without replying in an unformatted reply section... Hmph. I guess I'll edit your answer and let you delete it if it bugs you.

This is how I would do it in Java with better libraries:

public scanForEmployees(String filename) {
    GoodXMLLib source=new GoodXMLLib(filename);
    while( String[] employee: source.scanFor("employee", "firstname", "lastname") )
    {
          System.out.println("First Name: " + employee[0]);
          System.out.println("Last Name: " + employee[1]);
    }
} 

This is just a quick hack involving no magic and all reusable components. If I wanted to add some magic I could do something better than returning an array of string arrays, but even as is this GoodXMLLib would be completely reusable. The first parameter of scanFor is the section, all future parameters would be the items to find which is limited, but the interface could be buffed slightly to add multiple levels of matching with no real problem.

I will admit that Java has some pretty poor library support in general, but come on--to compare a horrible usage of Java's decade(?) old XML library to an implementation done based on being terse is just not fair--and is far from a comparison of the languages!

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • hmm, the Java example would be shorter and better looking with a SAX or StAX parser. But still the SCALA one is really nice – oluies Jun 04 '10 at 18:52
  • 5
    The Java code is written exactly to parse that particular XML file with no attempt at reuse and a lot of duplicated code. Whoever wrote it was either trying to deliberately look like he didn't understand coding or didn't understand coding. – Bill K Jul 02 '10 at 21:42
  • @Bill K: I have never done XML parsing in Java so I picked this example from some random site. Feel free to edit the Java part of the answer, I don't mind. – missingfaktor Jul 03 '10 at 04:33
  • Well, let's assume that you are talking language differences and not library differences--in that case, the two would be nearly identical. The only language difference in the second example is the match/case thing which could be done in a single line as a for loop if implemented that way by the library. – Bill K Jul 06 '10 at 16:07
  • @Bill K: No, you are completely wrong. There are two very powerful Scala features at work here: 1. XML Literals 2. Pattern Matching. Java doesn't have either of these. So the equivalent Java code written in some hypothetical library will sure NOT be identical. (Try writing, you'll know.) – missingfaktor Jul 06 '10 at 19:10
  • @Bill K: By the way, match-case is like a switch-case put on steroids. It's used for decision making, not looping. – missingfaktor Jul 06 '10 at 19:17
  • @Rahul G Updated your answer so I could get the text formatting. I admit the pattern matching COULD be more powerful, but it wasn't being used in this case--even if it was I could match it with an intelligently formed library for the most part using nested match statements and regular expressions. For me the biggest burden in languages is syntax--the less unique operators are part of a language, the easier it is to learn and fully understand. Case in point--a lot of syntax was added to this Scala solution for no reduction in code size--why? – Bill K Jul 06 '10 at 21:44
  • @Bill K: That's a very broad question and I'd suggest you post it as a separate question if you are really interested in knowing the answer. There are people on this forum who can answer it better than I can. – missingfaktor Jul 07 '10 at 05:37
  • @Bill: your hypothetical code is broken. How do you imagine `scanFor` to work, while being reusable at the same time (i.e. not just working for this *particular* use-case)? Scala has the edge because it does **not** use any specialized features or methods here, just plain Scala. Granted, XPath (or CSS selectors) *can* make the above Java code *much* easier but nowhere near as elegant as your hypothetical code, and XPath is as good as it gets. – Konrad Rudolph Jul 07 '10 at 10:59
  • @Konrad Rudolph it takes a filter showing a section to look in, scans for elements in that section, creates either an iterator or an array of string arrays and returns it. After being returned, the iterator/array is iterated over by the for loop returning an array of strings with each array entry [0] or [1] corresponds to one of the search terms. Additional search terms would make a longer return array-variable args. Could be more generic by allowing additional levels of filtering, but this more than solves the existing problem in a form that is very reusable. What do you think won't work? – Bill K Jul 07 '10 at 18:10
  • To make it more generic, try syntax such as: source.filter() .inGroup("company", "My Company") .inGroup("employee") .getFields( "firstname", "lastname"); That could gather all employees from "My Company" and return their names. I'm not saying this is the same as the Scala solution, I know Scala does part of this in the language--but it solves the same problem--and that was my point... that this particular Java solution was poor. – Bill K Jul 07 '10 at 18:24
8

I liked this simple example of sorting and transformation, taken from David Pollak's 'Beginning Scala' book:

In Scala:

def validByAge(in: List[Person]) = in.filter(_.valid).sortBy(_.age).map(_.first)
case class Person(val first: String, val last: String, val age: Int) {def valid: Boolean = age > 18}
validByAge(List(Person("John", "Valid", 32), Person("John", "Invalid", 17), Person("OtherJohn", "Valid", 19)))

In Java:

public static List<String> validByAge(List<Person> in) {
   List<Person> people = new ArrayList<Person>();
   for (Person p: in) {
     if (p.valid()) people.add(p);
   }
   Collections.sort(people, new Comparator<Person>() {
      public int compare(Person a, Person b) {
        return a.age() - b.age();
      } 
   } );
   List<String> ret = new ArrayList<String>();
     for (Person p: people) {
       ret.add(p.first);
     }
   return ret;
}

public class Person {
    private final String firstName;
    private final String lastName;
    private final Integer age;
    public Person(String firstName, String lastName, Integer age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    public String getFirst() {
        return firstName;
    }
    public String getLast() {
        return lastName;
    }
    public Integer getAge() {
       return age;
    }
    public Boolean valid() {
       return age > 18;
    }
}

List<Person> input = new ArrayList<Person>();
input.add(new Person("John", "Valid", 32));
input.add(new Person("John", "InValid", 17));
input.add(new Person("OtherJohn", "Valid", 19));

List<Person> output = validByAge(input)
kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Arjan Blokzijl
  • 6,878
  • 2
  • 31
  • 27
8

I'm writing a Blackjack game in Scala now. Here is how my dealerWins method would look in Java:

boolean dealerWins() {
    for(Player player : players)
        if (player.beats(dealer))
            return false;
    return true;
}

Here's how it looks in Scala:

def dealerWins = !(players.exists(_.beats(dealer)))

Hooray for higher-order functions!

Java 8 solution:

boolean dealerWins() {
    return players.stream().noneMatch(player -> player.beats(dealer));
}
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
MikeFHay
  • 8,562
  • 4
  • 31
  • 52
6

How about Quicksort?


Java

The following is a java example found via a google search,

the URL is http://www.mycstutorials.com/articles/sorting/quicksort

public void quickSort(int array[]) 
// pre: array is full, all elements are non-null integers
// post: the array is sorted in ascending order
{
   quickSort(array, 0, array.length - 1);   // quicksort all the elements in the array
}


public void quickSort(int array[], int start, int end)
{
   int i = start;      // index of left-to-right scan
   int k = end;        // index of right-to-left scan

   if (end - start >= 1)               // check that there are at least two elements to sort
   {
       int pivot = array[start];       // set the pivot as the first element in the partition

       while (k > i)                   // while the scan indices from left and right have not met,
       {
           while (array[i] <= pivot && i <= end && k > i) // from the left, look for the first
              i++;                                        // element greater than the pivot
           while (array[k] > pivot && k >= start && k >= i) // from the right, look for the first
              k--;                                          // element not greater than the pivot
           if (k > i)                  // if the left seekindex is still smaller than
               swap(array, i, k);      // the right index, swap the corresponding elements
       }
       swap(array, start, k);          // after the indices have crossed, swap the last element in
                                       // the left partition with the pivot 
       quickSort(array, start, k - 1); // quicksort the left partition
       quickSort(array, k + 1, end);   // quicksort the right partition
    }
    else // if there is only one element in the partition, do not do any sorting
    {
        return;                        // the array is sorted, so exit
    }
}

public void swap(int array[], int index1, int index2) 
// pre: array is full and index1, index2 < array.length
// post: the values at indices 1 and 2 have been swapped
{
   int temp      = array[index1];      // store the first value in a temp
   array[index1] = array[index2];      // copy the value of the second into the first
   array[index2] = temp;               // copy the value of the temp into the second
}

Scala

A quick attempt at a Scala version. Open season for code improvers ;@)

def qsort(l: List[Int]): List[Int] = {
  l match {
    case Nil         => Nil
    case pivot::tail => qsort(tail.filter(_ < pivot)) ::: pivot :: qsort(tail.filter(_ >= pivot))
  }
}
Don Mackenzie
  • 7,953
  • 7
  • 31
  • 32
  • 1
    Does that quicksort on linked lists have O(n^2) time complexity or not? Usually mergesort or similar is used for linked lists. – Esko Luontola Jun 02 '10 at 05:53
  • 4
    It's also not tail recursive and hence unsuitable as a performant algorithm (or one which will not overflow the stack) – oxbow_lakes Jun 02 '10 at 11:01
  • Thanks for the useful comments. I had seen quicksort written like this somewhere and was impressed by it's compactness, clearly I didn't give it much consideration. I got carried away by the LOC comparison, which is always a seductive thing with Scala v Java. – Don Mackenzie Jun 02 '10 at 21:47
  • 2
    Quicksort is not *O(n^2)* on functional lists, but it certainly has that danger. Asymptotically, it's still average *O(n log n)*, but there is a higher statistical probability of hitting the worst case *O(n^2)* because we always select the pivot point at the head of the list, rather than choosing one at random. – Daniel Spiewak Jun 03 '10 at 01:36
  • Filtering twice is bad. See in my answer to your question the use of `partition` to avoid that. – Daniel C. Sobral Jun 07 '10 at 03:52
6

I like much the method getOrElseUpdate, found in mutableMap and shown here, first Java, without:

public static Map <String, Integer> wordCount (Scanner sc, String delimiters) {
    Map <String, Integer> dict = new HashMap <String, Integer> ();
            while (sc.hasNextLine ()) {
                    String[] words = sc.nextLine ().split (delimiters);
                    for (String word: words) {
                        if (dict.containsKey (word)) {
                            int count = dict.get (word);
                            dict.put (word, count + 1);
                        } else
                            dict.put (word, 1);
                    }
            }       
    return dict;
}

yes - a WordCount, and here in scala:

def wordCount (sc: Scanner, delimiter: String) = {
        val dict = new scala.collection.mutable.HashMap [String, Int]()
        while (sc.hasNextLine ()) {
                val words = sc.nextLine.split (delimiter)
                words.foreach (word =>
                      dict.update (word, dict.getOrElseUpdate (word, 0) + 1))
        }
        dict
}

And here it is in Java 8:

public static Map<String, Integer> wordCount(Scanner sc, String delimiters)
{
    Map<String, Integer> dict = new HashMap<>();
    while (sc.hasNextLine())
    {
        String[] words = sc.nextLine().split(delimiters);
        Stream.of(words).forEach(word -> dict.merge(word, 1, Integer::sum));
    }
    return dict;
}

And if you want to go 100% functional:

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

public static Map<String, Long> wordCount(Scanner sc, String delimiters)
{
    Stream<String> stream = stream(sc.useDelimiter(delimiters));
    return stream.collect(groupingBy(identity(), counting()));
}

public static <T> Stream<T> stream(Iterator<T> iterator)
{
    Spliterator<T> spliterator = Spliterators.spliteratorUnknownSize(iterator, 0);
    return StreamSupport.stream(spliterator, false);
}

filter and sort have already been shown, but look how easy they are integrated with the map:

    def filterKeywords (sc: Scanner, keywords: List[String]) = {
            val dict = wordCount (sc, "[^A-Za-z]")
            dict.filter (e => keywords.contains (e._1)).toList . sort (_._2 < _._2)
    } 
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
user unknown
  • 35,537
  • 11
  • 75
  • 121
  • I like this example a lot. It avoids the easy route of comparing case classes, and doesn't make the mistake of showing Scala code and not the Java equivalent. – Daniel C. Sobral Jun 07 '10 at 04:03
6

I liked user unknown's answer so much I'm going to try to improve upon it. The code below is not a direct translation of the Java example, but it accomplishes the same task with the same API.

def wordCount (sc: Scanner, delimiter: String) = {
  val it = new Iterator[String] {
    def next = sc.nextLine()
    def hasNext = sc.hasNextLine()
  }
  val words = it flatMap (_ split delimiter iterator)
  words.toTraversable groupBy identity mapValues (_.size)
}
Community
  • 1
  • 1
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • I don't have scala-2.8 installed by now, to test this snippet, but I guess I can see what is intendet - just 'keywords' aren't used at all. It produces a map of all Strings and their frequencies, doesn't it? – user unknown Jun 07 '10 at 17:52
  • @user Yes, that's what it does. Isn't that what's accomplished by your code? Oh, I see. I copied the wrong line. I'm gonna fix it right now. :-) – Daniel C. Sobral Jun 07 '10 at 23:30
5

This is a very simple example: Square integers and then add them


    public int sumSquare(int[] list) {
        int s = 0;
        for(int i = 0; i < list.length; i++) {
            s += list[i] * list[i]; 
        }
        return s;
    }

In scala:


val ar = Array(1,2,3)
def square(x:Int) = x * x
def add(s:Int,i:Int) = s+i

ar.map(square).foldLeft(0)(add)

Compact map applies the function to all elements of the array, so:

Array(1,2,3).map(square)
Array[Int] = Array(1, 4, 9)

Fold left is will start with 0 as the accumulator (s) and apply add(s,i) to all the elements (i) of the array, so that:

 Array(1,4,9).foldLeft(0)(add)  // return 14 form 0 + 1 + 4 + 9

Now this can be further compacted to:

Array(1,2,3).map(x => x * x ).foldLeft(0)((s,i) => s + i )

This one I will not try in Java (to much work), turn XML to a Map:


<a>
   <b id="a10">Scala</b>
   <b id="b20">rules</b>
</a>

Another one liner to get the map from the XML:


val xml = <a><b id="a10">Scala</b><b id="b20">rules</b></a>

val map = xml.child.map( n => (n \ "@id").text -> n.child.text).toMap
// Just to dump it.
for( (k,v) <- map) println(k + " --> " + v)
Thomas
  • 2,095
  • 18
  • 24
  • 1
    The problem with your `sumSquare` in Scala is that it looks very cryptic to a Java developer, which will give them ammo against you to complain that Scala is obscure and complicated... – Jesper Jun 01 '10 at 20:53
  • I reformatted a bit to improved the example. Hope that this does not hurt Scala. – Thomas Jun 01 '10 at 21:14
  • 5
    scala> 1 to 10 map (x => x*x) sum res0: Int = 385 Let's see the java developer call that cryptic. At that point it's fingers in the ears saying nah-nah-nah. – psp Jun 02 '10 at 03:30
  • 3
    @Jesper To a non-Java developer, Java looks like vast amounts of boilerplate and line noise. That doesn't mean you can't get real work done in the language. – James Moore Jun 02 '10 at 13:18
  • You could use reduceLeft(add) instead of foldLeft(0)(add). I think it’s easier to read when your start element is the group’s zero/identity element. – Debilski Jun 02 '10 at 16:03
  • @James I agree, but if you want to convince Java developers that Scala is better (as is probably the case with the poster of the question) then it might be better to not start with something that might scare them... – Jesper Jun 02 '10 at 17:19
  • The Javacode isn't fair, since it doesn't use the simplified for loop: `for(int i : list.length) sum += i*i;`. – user unknown Apr 15 '12 at 07:01
5

Problem: you need to design a method that will execute any given code asynchronously.

Solution in Java:

/**
* This method fires runnables asynchronously
*/
void execAsync(Runnable runnable){
    Executor executor = new Executor() {
        public void execute(Runnable r) {
            new Thread(r).start();
        }
    };
    executor.execute(runnable);
}

...

execAsync(new Runnable() {
            public void run() {
                ...   // put here the code, that need to be executed asynchronously
            }
});

The same thing in Scala (using actors):

def execAsync(body: => Unit): Unit = {
  case object ExecAsync    
  actor {
    start; this ! ExecAsync
    loop {
      react {           
        case ExecAsync => body; stop
      }
    }
  }    
}

...

execAsync{  // expressive syntax - don't need to create anonymous classes
  ...  // put here the code, that need to be executed asynchronously    
}
Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
  • 6
    As of 2.8, this can be written as Futures.future{body} and is actually more powerful since the future returned by this can be joined to get the value it eventually evaluates to. – Dave Griffith Jun 23 '10 at 00:41
3

I am preparing a document that gives several examples of Java and Scala code, utilising only the simple to understand features of Scala:

Scala : A better Java

If you would like me to add something to it, please reply in the comments.

HRJ
  • 17,079
  • 11
  • 56
  • 80
3

The Circuit Breaker pattern from Michael Nygard's Release It in FaKods (link to code)

implementation looks like this in Scala:

. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(100,10))
. . .


class Test extends UsingCircuitBreaker {
  def myMethodWorkingFine = {
    withCircuitBreaker("test") {
      . . .
    }
  }

  def myMethodDoingWrong = {
    withCircuitBreaker("test") {
      require(false,"FUBAR!!!")
    }
  }
}

Which I think is super nice. It looks just as a pice of the language but it is a simple mixin in the CircuitBreaker Object doing all work.

/**
 * Basic MixIn for using CircuitBreaker Scope method
 *
 * @author Christopher Schmidt
 */
trait UsingCircuitBreaker {
  def withCircuitBreaker[T](name: String)(f: => T): T = {
    CircuitBreaker(name).invoke(f)
  }
}

Reference in other languages Google for "Circuit breaker" + your language.

oluies
  • 17,694
  • 14
  • 74
  • 117
2

Lazily evaluated infinite streams are a good example:

object Main extends Application {

   def from(n: Int): Stream[Int] = Stream.cons(n, from(n + 1))

   def sieve(s: Stream[Int]): Stream[Int] =
     Stream.cons(s.head, sieve(s.tail filter { _ % s.head != 0 }))

   def primes = sieve(from(2))

   primes take 10 print

}

Here is a question addressing infinite streams in Java: Is an infinite iterator bad design?

Another good example are first class functions and closures:

scala> def f1(w:Double) = (d:Double) => math.sin(d) * w
f1: (w: Double)(Double) => Double

scala> def f2(w:Double, q:Double) = (d:Double) => d * q * w
f2: (w: Double,q: Double)(Double) => Double

scala> val l = List(f1(3.0), f2(4.0, 0.5))
l: List[(Double) => Double] = List(<function1>, <function1>)

scala> l.map(_(2))
res0: List[Double] = List(2.727892280477045, 4.0)

Java doesn't support first class functions, and mimicking closures with anonymous inner classes isn't very elegant. Another thing this example shows that java can't do is running code from an interpreter/REPL. I find this immensely useful for quickly testing code snippets.

Community
  • 1
  • 1
dbyrne
  • 59,111
  • 13
  • 86
  • 103
  • Please note that the sieve is too slow to be practical. – Elazar Leibovich Jun 02 '10 at 04:12
  • @oxbow_lakes there is no equivalent java for these examples. – dbyrne Jun 03 '10 at 12:51
  • @dbyme Not true. You can easily subclass Java's `Iterable` and `Iterator` to produce infinite streams. – Daniel C. Sobral Jun 09 '10 at 15:52
  • @dbyrne "Another thing this example shows that java can't do is running code from an interpreter/REPL. I find this immensely useful for quickly testing code snippets." I use a scrapbook page in Eclipse for trying out Java snippets. Doing most if not all Java work in that IDE, I need no REPL. I used notepad.exe and javac in my early days when I was unsure about a language or library feature and after a short time that went very well and fast - although a REPL is somewhat easier to use - and faster. I could have avoided the notepad hack altogether by installing VisualAge which we had already in –  May 13 '11 at 13:34
2

Why nobody posted this before:

Java:

class Hello {
     public static void main( String [] args ) {
          System.out.println("Hello world");
     }
}

116 characters.

Scala:

object Hello extends App {
     println("Hello world")
}

56 characters.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 1
    `Application` trait considered harmful... http://www.scala-blogs.org/2008/07/application-trait-considered-harmful.html – missingfaktor Jun 03 '10 at 06:06
0

This Scala code...

def partition[T](items: List[T], p: (T, T) => Boolean): List[List[T]] = {
  items.foldRight[List[List[T]]](Nil)((item: T, items: List[List[T]]) => items match {
    case (first :: rest) :: last if p (first, item) =>
      (List(item)) :: (first :: rest) :: last
    case (first :: rest) :: last =>
      (item :: first :: rest) :: last
    case _ => List(List(item))
  })
}

...would be completely unreadable in Java, if possible at all.

JUST MY correct OPINION
  • 35,674
  • 17
  • 77
  • 99
  • 10
    MY correct OPINIO: thanks for the answer! but could you please explain what happens there? I'm not familiar with Scala syntax yet, and (that's the possible reason why) it looks completely unreadable even now for me. – Roman Jun 02 '10 at 14:26
  • It's partitioning a generic list of type T using a provided partitioning function as a guard in the pattern matching clauses of the case statement. – JUST MY correct OPINION Jun 02 '10 at 14:35
  • 3
    Weird. I'm not even remotely a Scala expert and can figure that out. – JUST MY correct OPINION Jun 02 '10 at 17:07