Java 8 gearing up for release, why Java 8 will be a top contender for Java.next languages in 2014?

Java 8 will go GA in March 2014. java8_logo The first proposed final draft of Java 8 JSR 337 was released early this week. One of the main components of this JSR is Lambda Expressions for the language (JSR 337). This brings the functional constructs to the language, which will undeniably make Java a top contender among other functional peers (Scala, Groovy, Clojure) on the JVM for Java developers. Conciseness is only part of the story, check out how Java 8 programs start to look with Lambda expressions. While being concise for a casual reader, it clearly makes a case why thinking functional may benefit to Java developers in terms of the powerful constructs it offers. The conciseness does not take away readability of the Java program, instead it makes Java developers feel home and enables functional programming with ease, taking away the heavy lifting usually required for moving away from OO paradigm.

I stole the name “Java.next” from Neal Ford‘s excellent series of articles about functional languages on the JVM. The latest installment of the series was “Java.next: Functional coding styles”. While, the article takes on legacy Java, adding Java 8 to the mix would not hurt. So, let us take his example where you are given a list of names, some of which consist of a single character. You are asked to return the names in a comma-delimited string that contains no single-letter names, with each name capitalized. Here are the various flavors of the implementation taken from the article, while Scala, Groovy and Clojure has its functional version, Java’s implementation is imperative and old school.

Java version:


public class TheCompanyProcess {
public String cleanNames(List<String> listOfNames) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < listOfNames.size(); i++) {
if (listOfNames.get(i).length() > 1) {
result.append(capitalizeString(listOfNames.get(i))).append(",");
}
}
return result.substring(0, result.length() – 1).toString();
}
public String capitalizeString(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
}
}

view raw

gistfile1.java

hosted with ❤ by GitHub

Scala version:


val employees = List("neal", "s", "stu", "j", "rich", "bob")
val result = employees
.filter(_.length() > 1)
.map(_.capitalize)
.reduce(_ + "," + _)

view raw

gistfile1.scala

hosted with ❤ by GitHub

Groovy version:


class TheCompanyProcess {
public static String cleanUpNames(List listOfNames) {
listOfNames
.findAll {it.length() > 1}
.collect {it.capitalize()}
.join(',')
}
}

Clojure version:


(defn process [list-of-emps]
(reduce str (interpose ","
(map clojure.string/capitalize
(filter #(< 1 (count %)) list-of-emps)))))

view raw

gistfile1.clj

hosted with ❤ by GitHub

Happy Holidays from the islands

Java 8 version of functional processing

With Java 8, functional interfaces makes this possible with Lambda expressions and Streams make you even more fun when working with Collections in Java 8. Here is the functional version in Java 8.


employees.stream()
.filter(e -> e.length() > 1)
.map(s -> s.substring(0, 1).toUpperCase() + s.substring(1))
.collect(joining(","));

view raw

gistfile1.java

hosted with ❤ by GitHub

Switch it to parallelStream() for parallel processing, as simple as that to kick the tires of your cores.


employees.parallelStream()
.filter(e -> e.length() > 1)
.map(s -> s.substring(0, 1).toUpperCase() + s.substring(1))
.collect(joining(","));

view raw

gistfile1.java

hosted with ❤ by GitHub

My original intent was to compare with the Java.next languages as perceived by Neal Ford in his article. It is unfair to leave behind some of the cool languages on the JVM. Thanks Luke for bringing this up. I strongly believe top-notch IDE support (Eclipse or Intellij) is a win-win situation for users and language implementors. With that context, I updated my list to include Fantom, Gosu, Xtend, Kotlin, Ceylon in order of their age (oldest first).

Fantom version:


static Void main() {
employees := ["neal", "s", "stu", "j", "rich", "bob"]
Str result := employees.findAll { it.size > 1 }
.map { it.capitalize }
.join(",")
}

view raw

gistfile1.fan

hosted with ❤ by GitHub

Gosu version


var employees = { "neal", "s", "stu", "j", "rich", "bob" }
var result = employees.where(\s > s.length > 1)
.map(\s > s.capitalize())
.join(",")

view raw

gistfile1.gs

hosted with ❤ by GitHub

Xtend version:


def static void main(String[] args) {
val employees = Arrays.asList("neal", "s", "stu", "j", "rich", "bob")
val result = employees.stream
.filter[length() > 1]
.map[toFirstUpper()]
.reduce[x, y | x + "," + y]
}
// without map()
def static void main(String[] args) {
val employees = Arrays.asList("neal", "s", "stu", "j", "rich", "bob")
val result = employees.stream
.filter[length() > 1]
.reduce[x, y | x.toFirstUpper + "," + y.toFirstUpper]
}

view raw

gistfile1.xtend

hosted with ❤ by GitHub

Kotlin version:


fun main(args: Array<String>) {
val employees = array("neal", "s", "stu", "j", "rich", "bob")
val result = employees filter { it.length > 1 } map { it.capitalize() } reduce { x, y -> x + "," + y }
}

view raw

gistfile1.kt

hosted with ❤ by GitHub

Ceylon version:


void main() {
value employees = {"neal", "s", "stu", "j", "rich", "bob"};
String result = ",".join(employees
.filter((String e) => e.longerThan(1))
.map((String s) => s.segment(0, 1).uppercased + s.spanFrom(1))
);
// using a for comprehension
String result = ", ".join {
for (i in employees)
if (i.longerThan(1))
i.segment(0, 1).uppercased + i.spanFrom(1)
};
}

Personally, I feel Java 8 and Groovy has better success rate in making developers stay in their comfort zone and still enjoy functional prowess. While, I agree Clojure and Scala versions make their case to different set of developers, I believe maintaining a larger code base will be a challenge, when time to develop and market is ever shrinking, and bringing someone up-to-speed with these language tricks will not be easy. If it looks good, eat it, does not play well when it comes to programming in general. While coming to the newer JVM languages, parallelism is one factor that makes Java 8 easy peasy to deal with. These new breed of languages bring ton of cool features (topic for another blog post!) and attracts developers to the JVM, not just Java developers, which is good for the platform. It remains to be seen in the coming years how well these languages get adopted in mainstream development.

Merry Christmas and Happy New Year everyone!

Update (12/29/2013) : Updated the Java.next languages comparison to include newer JVM languages: Fantom, Gosu, Xtend, Kotlin, Ceylon.

8 thoughts on “Java 8 gearing up for release, why Java 8 will be a top contender for Java.next languages in 2014?

  1. I personally believe that the new Streams API along with lambdas and extension methods will be such a huge boost for Java 8’s popularity that alternative JVM languages will suffer from a huge loss of traction. Granted, there would be dozens of other useful features to be added, such as these ones from Ceylon:
    http://blog.jooq.org/2013/12/03/top-10-ceylon-language-features-i-wish-we-had-in-java/

    Butthe Streams/Lambda/Extension Methods combo is really the essence of it. Looking forward to 2014!

    Like

    1. Lukas, I could not agree more. Ceylon and the recent storm of JVM languages offer something for everyone and makes JVM a perfect platform to develop for.

      Like

    1. If it’s assumed, as many of the examples did, that the “employees” list exists, then even more simple…

      >> employees
      .findAll {it.length() > 1}
      .collect {it.capitalize()}
      .join(‘,’)

      And if line length is important, as the Kotlin example seemed to suggest, then a single line expression could be written…

      >> employees.findAll {it.length() > 1}.collect {it.capitalize()}.join(‘,’)

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s