Coming Up for Air

String.split(), Java 8 style

Today I found myself with a common problem: I had a delimited string of an unknown number of parts that that I needed split apart and process. Prior to Java 8, implementing that might looked something like this:

for (String part : string.split("\\n")) {
    if (!myList.contains(part)) {
        if (!part.isEmpty()) {
            myList.add(part);
        }
    }
}

While that works and seems to be pretty efficient, I felt it could use a stream makeover, as I find the stream operations to be clearer and more concise. What I ended up with was something like this:

Pattern.compile("\\n")
    .splitAsStream(string)
    .filter(s -> !myList.contains(s))
    .forEach( s -> myList.add(s));

I could also have used Arrays.stream() rather than Pattern:

Arrays.stream(string.split("\\" + DELIMITER))
    .filter(s -> !myList.contains(s))
    .filter(s -> !s.isEmpty())
    .forEach(s -> myList.add(s));

I haven’t done any profiling to see if Pattern.compile() has any non-negligible performance impact versus String.split() (and I probably won’t, but you can easily "cache" the compiled pattern in an instance or static variable if needed :), but I will point out this difference: when using split(), streamed or not, we may get a blank value in some situations, so we need to check for that (notice the calls to String.isEmpty() in both of those implementations). With the Pattern-based implementation, we don’t have that problem.

At any rate, there you have it: you can convert String.split() to a stream-based implementation fairly easily, and, I think, get more readable code out of it. Any performance implications are left as an exercise for the reader. :)

Chesterton's Fence and the Software Developer

Recently at work, we found an odd scenario with a REST (-ish ;) endpoint from another team: If the request provided a list of, say, 11 IDs in the query string, the system would only return information on the first 10 of them, silently dropping anything over that seemingly odd limit. The initial reaction was of, course, "Well, let’s just increase the limit." To be honest, I had the same reaction, but then I remembered one of my favorite quotes, known as Chesteron’s Fence:

In the matter of reforming things, as distinct from deforming them, there is one plain and simple principle; a principle which will probably be called a paradox. There exists in such a case a certain institution or law; let us say, for the sake of simplicity, a fence or gate erected across a road. The more modern type of reformer goes gaily up to it and says, "I don’t see the use of this; let us clear it away." To which the more intelligent type of reformer will do well to answer: "If you don’t see the use of it, I certainly won’t let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it."

— G.K. Chesterton

Chesterton’s context, politics in Great Britain of the 1920s, is, of course, quite different from a software development shop almost 100 years later, but the message is still extremely appropriate: Before you go tearing things down or otherwise changing something you’ve found, you really need to understand not only what you’re changing, but why it was made that way in the first place.

In the case of this REST call, we should ask questions like

  • Are there system load concerns, such as memory or processing time?

  • Are there concerns about the on-the-wire response size?

  • Was there an explicit Product Management decision to set the limit this low for business reasons we don’t see reflected in the code?

And so on. Until we can answer those questions (or reasonably rule them out as relevant), we need to be very hesitant in making the change. Once we’ve explained the original developer(s) built that fence, then we can talk about ripping it down.

Getting JavaFX ListViews to Honor Container Width

I recently struggled trying to text in a JavaFX ListView to wrap inside the container like I asked it to, rather than extend (and disappear) past the boundaries of the container. After some discussion on Twitter and a bit of Googling, I found an answer that I thought I’d share here to, perhaps, save someone some time.

Compiling for Java 8 and Java 9

In a project I’m working on for my book, I need to share classes between two applications. One, an Android project, requires Java 8. The other, a desktop JavaFX application, needs to run under Java 9, complete with module support. The problem with this is that the Maven tooling isn’t quite ready for Java 9, so it’s not as simple as I would like. I have, however, found a solution that seems to work.

JavaFX Frameworks

In my work on my book, I’ve spent quite a bit of time with JavaFX. In the chapter I just submitted, I wrote the application using the NetBeans RCP, which I think is a great piece of software. My only "complaint", I think, is more of a philosophical one more than a technical one, and even stating it that way is probably really over-selling it: for the most part, to use the RCP is to use Swing. Sure, you can use JavaFX in the application, but it seems you have to hold your mouth just right to get two-way data flow working. Possible, but it seems like a bit of work.

At any rate, while casting around The Tubes to track down advice on how to solve one problem or another, I ran across a couple of more modern application frameworks that look really promising, Drombler FX and the Dolphin Platform. Both look pretty slick, but the former seems to be backed by "only one guy" and might be a bit slow moving, while Dolphin is backed by Canoo and, more specifically, Michael Heinrichs, Hendrik Ebbers, Dierk König.

Once I finish this book and have more time to play with shiny new things, I need to give both of these a spin.

I should probably note, though, that there’s nothing really wrong with the NetBeans RCP in any real technical sense (beyond the 'no software is perfect' notion). I just like shiny things. I did, though, successfully create my RCP app and found the experience to be quite nice. If you need a desktop application, you should definitely check out the RCP.

Quotes

Sample quote

Quote source