And even cooler than when I got to touch my book, Scott and I both got our author copies today.
I’ve certainly been enjoying showing it to everyone I know.
And even cooler than when I got to touch my book, Scott and I both got our author copies today.
I’ve certainly been enjoying showing it to everyone I know.
In Java 8, Oracle introduced the new Nashorn engine and is encouraging the use of jjs. It’s a RPEL (read print evaluate loop) for JavaScript. Since JavaScript can call Java, this allows experimenting with Java APIs like you do in other languages like Python and Ruby. It works better in those languages though.
Cay Horstmann’s book, Java SE 8 for the Really Impatient, had good exercises for lambdas so I decided to the end of chapter exercises for Nashorn.
Exercise 1 – Play with jjs to experiment with an API you want to explore; did you find it easier than writing test programs in Java?
Nope. The so called advantage of using jjs is that you don’t need to write the plumbing code. But an IDE can generate a class and main method in a couple clicks.
Exercise 2 – Using JJS and the stream library iteratively work out a solution to the problem to print a filtered list of unique long words in sorted order and see how it compares to your usual workflow.
Here was my workflow with jjs:
Attempt # | Code | Error | Comments |
---|---|---|---|
1 | jjs> var paths = Paths.get(‘path/words.txt’) | <shell>:1 ReferenceError: “Paths” is not defined | Forgot to type the package name. Don’t know it by heart anyway. Need to look it up in the JavaDoc. |
2 | jjs> var paths = java.nio.file.Paths.get(‘path/words.txt’) | Success |
Attempt # | Code | Error | Comments |
---|---|---|---|
1 | jjs> List<String> list = java.nio.files. Files.readAllLines(path) | ECMAScript Exception: ReferenceError: <shell>:1:11 Invalid left hand side for assignment | It’s JavaScript, not Java so no type declaration. Should just use var. |
2 | jjs> var list = java.nio.files. Files.readAllLines(path) | <shell>:1 ReferenceError: “path” is not defined | Typo in variable name. I wish I named it path, not paths. But I want to do the exercise in order and not go back. |
3 | jjs> var list = java.nio.files. Files.readAllLines(paths) | java.lang.RuntimeException: java.lang. ClassNotFoundException: java.nio.files. Files.readAllLines | Typo in package name. It should be file and not files |
4 | jjs> var list = java.nio.file. Files.readAllLines(paths) | java.lang.RuntimeException: java.nio.file. NoSuchFileException: path/words.txt | Missing forward slash in path name. On the bright side, I can rename the variable without feeling like I’m messing up the experiment. |
5 | jjs> var path = java.nio.file. Paths.get(‘/path/words.txt’) | Worked as expected (but at this point, I’m typing into this blog post and copy/pasting into the jjs console | |
6 | jjs> var list = java.nio.file. Files.readAllLines(paths) | java.lang.RuntimeException: java.nio.file. NoSuchFileException: path/words.txt | Sigh. Didn’t use the corrected variable name |
7 | var list = java.nio.file. Files.readAllLines(path) | Worked as expected |
Attempt # | Code | Error | Comments |
---|---|---|---|
1 | jjs> list.stream().grep({ l -> l.length() > 12}) | ECMAScript Exception: SyntaxError: <shell>:1:23 Expected : but found – | This is completely wrong. Aside from the stream() call, it is using Groovy syntax. (I code Groovy at a command line so my fingers started there) |
2 | jjs> list.stream().filter( l -> l.length() > 12) | ECMAScript Exception: SyntaxError: <shell>:1:30 Expected an operand but found | Hmm. Puzzled. it looks right this time. I copy/pasted into my IDE and it compiled. I then started searching online and found out that you have to use a function literal. (This was in the book. I forgot about it) |
3 | jjs> list.stream().filter(function(e) { return e.length() > 12 }) | Prints reference to stream (as does Java.) Now can add the print | |
4 | jjs> list.stream().filter(function(e) { return e.length() > 12 }).forEach(System.out::println) | ECMAScript Exception: SyntaxError: <shell>:1:79 Expected , but found : | Not surprised that :: doesn’t work since -> doesn’t. Now for the long way. |
5 | jjs> list.stream().filter(function(e) { return e.length() > 12 }).forEach(function(e) { print(e) }) | Works as expected |
Attempt # | Code | Error | Comments |
---|---|---|---|
1 | jjs> list.stream().filter(function(e) { return e.length() > 12 }).sorted().forEach(function(e) { print(e) }) | Sorting worked | |
2 | jjs> list.stream().filter(function(e) { return e.length() > 12 }).sorted().distinct().forEach(function(e) { print(e) }) | Uniqueness filter worked | |
3 | jjs> list.stream().filter(function(e) e.length() > 12 ).sorted().distinct().forEach(function(e) print(e) ) | Remove unneeded code |
My thoughts
That was so far away from being easier that it was ridiculous. I’m comfortable with the NIO and lambda APIs. This shouldn’t have been hard. The Java version is:
import java.io.*; import java.nio.file.*; import java.util.*; public class Exercise2 { public static void main(String[] args) throws IOException { Path path = Paths.get("/path/words.txt"); List<String> list = java.nio.file.Files.readAllLines(path); list.stream() .filter(l -> l.length() > 12) .sorted() .distinct() .forEach(System.out::println); } }
Oracle released the OCA Java SE 8 Programmer I certification today. There are 77 questions and you get 2 hours to take the exam. The passing score is 65%. The topics have not changed since the beta.
You may already know that Scott and I wrote a study guide for this exam. The Kindle edition is already out. As of January 8th, the publisher was still working on posting the downloadable materials (3 mock exams, flashcards and glossary) that go with it. You can download those once they become available if you’ve bought the Kindle edition (or hard copy.) The hard copy is available for pre-order, but has not yet shipped.
We look forward to seeing your comment and questions in the OCAJP forum at CodeRanch. Also, you can see our book page for any errata or updates about the exam.