Pattern Matching, Averaging Run Times, BFG

CodeFX Occasionally #73 — 16th of June 2019

Nicolai Parlog
Jun 21, 2019 · 7 min read

Hi everyone,

and a good Sunday evening! ☀️ Around here it is indeed sunny and I had a great time yesterday evening hanging out by the Rhine, enjoying good company and a nice sunset. Small complication: tons of mosquitoes. My family took to counting the bites today and we ended up at about 135. 😲

Anyways, here’s a little read on how pattern matching will show up in Java, what to do when you need to run a command a few times and average its run time, as well as a new Project of the Week — a segment I’ve renamed since it’s not even close to being weekly anymore.

I send this newsletter out some Fridays. Or other days. Sometimes not for weeks. But as an actual email. So, subscribe!


Uses of pattern matching

At FOSDEM 2019, Brian Goetz gave a talk Java Language Futures, one of his recurring peaks into how Java will change over the next years, and there were a few uses for pattern matching that I found quite interesting. I’ll present them here, but first I want to point out that while this kind of pattern matching will be usable by switch expressions, they are not identical to it and, as you will see next, have a life of their own.

In the first phase, patterns will combine a condition, an extraction, and an assignment into one operation. Instead of this …

if (obj instanceof Integer) {
int intValue = ((Integer) obj).intValue();
// use `intValue`
}

… we’ll be able to write this …

if (obj instanceof Integer intValue) {
// use `intValue`
}

Brian says that “this simple thing will eliminate almost 100% of the casts in Java code, so that’s pretty nice”. I agree. 😁

Another neat aspect is that a variable that is declared with instanceof will be available immediately, so you can use it throughout the rest of the expression. Think of a typical equals implementation:

@Override
public final boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Employee))
return false;
Employee employee = (Employee) o;
return firstName.equals(employee.firstName)
&& lastName.equals(employee.lastName);
}

Although the use of instanceof is not actually that typical and requires equals to be final - a detail Brian himself omitted from the slides. Anyway, with a pimped instanceof that could be much simpler:

@Override
public final boolean equals(Object o) {
return this == o
|| (o instanceof Employee employee)
&& firstName.equals(employee.firstName)
&& lastName.equals(employee.lastName);
}

Requires you to know operator precedence for || and &&, but is otherwise much clearer and shorter.

This one has already been presented several times with regards to switch expressions and their use of patterns in case labels. It's pretty straightforward: Because case doesn't understand types, even after phase 1 you would have to write code like this:

Object value = // ...
String formatted = "unknown";
if (value instanceof Integer i)
formatted = String.format("int %d", i);
else if (value instanceof Byte b)
formatted = String.format("byte %d", b);
else if (value instanceof Long l)
formatted = String.format("long %d", l);
else if (value instanceof Double d)
formatted = String.format("double %f", d);
else if (value instanceof String s)
formatted = String.format("string %s", s);

Taking switch expressions and upgrading their case labels to understand types lets you write this instead:

Object value = // ...
String formatted = switch (value) {
case Integer i -> String.format("int %d", i);
case Byte b -> String.format("byte %d", b);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> "unknown " + value.toString();
};

Much clearer!

In this talk, Brian only alluded to deconstruction, and while he mentioned that it may follow the first two phases, this is no fixed plan. Heck, only phase one even has a JEP, so none of this is set in stone. Anyways, because he explained deconstruction elsewhere, I’m gonna continue with it here.

Imagine the JVM knew how to take a specific kind of object, let’s call it a record, apart into it’s constituting fields. For example it knows that, in a simple expression tree API, the Node implementation IntNode has an int field (it represents a number in an arithmetic expression). NegNode has another Node as a field (it negates that node's result) and AddNode has two Node fields (it adds their results).

Then you could evaluate such a tree as follows:

public int eval(Node n) {
return switch(n) {
case IntNode(int i) -> i;
case NegNode(Node n) -> -eval(n);
case AddNode(Node left, Node right) ->
eval(left) + eval(right);
};
}

Of course this looks like a case for simply defining an eval method on Node and implementing it in IntNode, NegNode, and AddNode, but you get the point: A pattern that can deconstruct instances of certain types can lead to very expressive, i.e. clear and concise, code. I really like it!


Averaging run times

When experimenting with application class-data sharing, which speeds up JVM starts, I wanted to measure the time it takes to launch the application. On Linux, time is there for you. It's pretty crude to just take the time once and be done with it, though, so I wanted to at least launch it a few times and take the average. But how? Manually?! Flower that! (Family told me I swear too much - guess what "flower" stands for...)

Luckily, StackOverflow was there for me:

#!/bin/bashrm -f /tmp/mtime.$$for x in {1..10}
do
/usr/bin/time -f "real %e user %U sys %S" -a -o /tmp/mtime.$$ $@
tail -1 /tmp/mtime.$$
done
awk '{ et += $2; ut += $4; st += $6; count++ } END {
printf "Average:\nreal %.3f user %.3f sys %.3f\n",
et/count, ut/count, st/count }' /tmp/mtime.$$

Put that into a script, maybe add a parameter for the number of repetitions and there you go: Repeat the same commend 10 (or n) times and see the average results of time.


Project showcase: BFG Repo Cleaner

The BFG is a simpler, faster alternative to git-filter-branch for cleansing bad data out of your Git repository history:

* Removing Crazy Big Files
* Removing Passwords, Credentials & other Private data

The git-filter-branch command is enormously powerful and can do things that the BFG can’t — but the BFG is much better for the tasks above, because:

* Faster : 10–720x faster
* Simpler : The BFG isn’t particularily clever, but is focused on making the above tasks easy
* Beautiful : If you need to, you can use the beautiful Scala language to customise the BFG. Which has got to be better than Bash scripting at least some of the time.

At Disy we moved from Subversion to Git some time ago, and BFG came in really handy to kick a few of those accidentally committed heap dumps out of 15 years of Subversion history. Recommended.


What I’ve been up to

Nothing that’s publicly visible. Yet. I spend most of the week putting together Accento’s proper site. The thing you see now is just a Save the date page that we put up as quickly as possible. The proper site will of course show talk abstracts, training summaries, speaker profiles, and whatnot. You know, why not just show you? Here’s a super-secret nothing-is-final please-don’t-share-because-URL-will-change preview: <redacted for Medium repost>.

(I’ve put this together with Gatsby.js, which was very interesting and a lot of fun. I’ll continue working on it on stream over the next week, but I don’t know the dates yet. Check out Twitch on Monday morning to see the new schedule if you want to hang out.)

The other thing I did, and you’re not gonna believe this, was go through the final PDF for The Java Module System before it goes to print. It should be at the printer as we speak, which means it’ll be another three to five weeks before a box of them arrive at my door step. I assume deliveries will start around the same time, so those of you who MEAP’ed a copy, should get their dead-tree version soonish. Thank you very much for your patience, I do not deserve it. 😔



PS: Don’t forget to subscribe or recommend! :)

Image by msandersmusic from Pixabay

CodeFX Weekly

Whatever caught my interest throughout the week: libraries or tools I am using, what I’ve written or read that might interest you, fascinating questions on StackOverflow, conferences visits, odd tweets, anything really that connects to Java, software development, or writing.

Nicolai Parlog

Written by

Developer (mostly Java), blogger (http://codefx.org/), author (http://tiny.cc/jms), trainer (http://courses.codefx.org & https://www.youtube.com/c/codefx)

CodeFX Weekly

Whatever caught my interest throughout the week: libraries or tools I am using, what I’ve written or read that might interest you, fascinating questions on StackOverflow, conferences visits, odd tweets, anything really that connects to Java, software development, or writing.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade