Java 8 is the biggest advance in the Java language since, well, Java 1, even bigger than the addition of generics in Java 5. I figured that every Java programmer would want to come up to speed quickly with these changes and wrote a short and snappy book “Java 8 for the Really Impatient”. A “rough cuts” version is now available on Safari.
In my French class, we are reading Marcel Pagnol’s “La gloire de mon père”. It never ceases to amaze me how much more complex and arbitrary human languages are compared to programming languages. Could you imagine a programming language with irregular verbs or the subjunctive mood?
As an aside, when I teach the introductory programming class, my students are aghast that they need to submit several programming homeworks per week. Clearly, they haven’t taken French. My French professors have routinely ruined my weekends with demands for written summaries of fifty+ page readings, or a couple hundred mind-numbing exercises on the subjunctive mood.
Back to topic, Marcel's dad claims that the longest word in the French language is “anticonstitutionnellement”. So, how would we verify this in Java?
In Linux, /usr/share/dict/french
has French words from a
to zygomatiques
, one per line. So, let's read them and print the longest, using the latest features of Java 8:
Path path = Paths.get("/usr/share/dict/french"); try (Stream<String> lines = Files.lines(path)) { Optional<String> longest = lines.max(Comparator.comparingInt(String::length)); longest.ifPresent(System.out::println); }
That’s certainly more concise than the traditional way:
Scanner in = new Scanner(new File("/usr/share/dict/french"), "UTF-8"); String longest = null; while (in.hasNextLine()) { String line = in.nextLine(); if (longest == null || longest.length() < line.length()) { longest = line; } } if (longest != null) { System.out.println(longest); }
It is also just as efficient. The stream doesn't actually store all lines, but lazily fetches them when needed.
But there is a fair amount of new jargon to master.
Optional<T>
is a null
-safe wrapper. Since it's possible for a stream to be empty, max
returns an Optional
result.ifPresent
method takes a function argument. If the Optional
contains a value, that value is passed to the function. Here, we use the function that maps x
to System.out.println(x)
, which can be more concisely written as a method expression System.out::println
.max
method takes a comparator. The Comparator
interface has a static (!) method comparing
. It makes a comparator from a function that extracts “key information” from objects in some way. In our case, the key that we want to use for comparison is the string length, again written as a method expression String::length
. (Actually, if you look closely, you'll see that I used comparingInt
, not comparing
. That avoids boxing int
into Integer
values.)Files.lines
method produces a stream of lines for a given path. Mercifully, the default character encoding is UTF-8, not the platform encoding. Previous APIs for readers and scanners used the platform encoding by default, which has bitten me more than once.Path
class and try
-with-resources block so that the stream (and the underlying file) is closed automatically.So, how is one to pick up all that new jargon? I wanted a short book that covers everything that is new in Java 8, without also teaching me what I already know. No such book existed, so I had to write it.
If you or your company subscribes to Safari Books Online, check out the Rough Cut of “Java 8 for the Really Impatient”. In a short 200 pages, I cover lambdas, streams, concurrency, the new date/time API, Nashorn, Java FX, and more. No religion, just the facts, for experienced Java programmers, and organized for easy learning and easy reference. (In fact, I had to look up a couple of details from the book for writing the code in this blog. I had no trouble finding them :-))