POSTS

Scala Collection API:s vs Java 8 Streams

Inspired by this article http://blog.informatech.cr/2013/03/24/java-streams-preview-vs-net-linq/ written by Edwin Dalorzo I wanted to do the same thing but with the Scala collection API to get a feel for how the upcoming Java 8 Stream API compares. I have selected a subset of the streams examples from Edwins blog entry, just copying his Java solution to each, so props to him for them!

Challenge 1: Filtering

Say we have a List of names and we want to find each name that contains the substring “am”:

Java 8 Streams

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> filteredNames = stream(names)
                 .filter(c -> c.contains("am"))
                 .collect(toList());

Scala

val names = List("Sam", "Pamela", "Dave", "Pascal", "Erik")
val filteredNames = names.filter(_.contains("am"))

Challenge 2: Indexed Filtering

Find all names in a list of names where the length of the name is less than or equal to the index of the name in the list + 1.

Java 8 Streams

This is a bit messy, since as Edwin notes there is no native way of getting the index of an entry in the streams API:s

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

List<String> nameList;
Stream<Integer> indices = intRange(1, names.length).boxed();
nameList = zip(indices, stream(names), SimpleEntry::new)
            .filter(e -> e.getValue().length() <= e.getKey())
            .map(Entry::getValue)

Scala

Of course this gets easier in Scala since scala does have a way to get the index in the list. This is done with the zipWithIndex operation which returns a new collection that has each entry as a tuple of the vale and the position in the collection. As an additional trick we can use collect instead of filter and then map to do both operations at the same time.

val names = List("Sam", "Pamela", "Dave", "Pascal", "Erik")
names.zipWithIndex.collect {
  case (name, index) if (name.length <= (index + 1)) => name
}

Challenge 4: Selecting many / Flattening

Take the values out of multiple maps and concatenate them:

Java 8 Streams

List<String> nameList1 = asList("Anders", "David", "James",
                                "Jeff", "Joe", "Erik");
nameList1.stream()
     .map(c -> "Hello! " + c)
     .forEach(System.out::println);