Interesting Links, 15 Feb 2016

  • A great quote from ##java: < surial> maven/gradle are to ant, as svn is to cvs.
  • JavaCPP is a new project that attempts to bridge a gap between C++ and Java, entering the muddy waters along with JNI and JNA (as well as a few other such projects). It actually looks pretty well done – and targets Android as well as the JVM, which seems like a neat trick.
  • First in a couple from DZone: “Reactive Programming by Example: Hands-On with RxJava and Reactor” is a presentation (thus a video) of a use of RxJava. Reactive programming is one way to introduce a scalable processing model to your code, although it’s hardly the only one (and it’s not flawless, either, so if you’re one of the anti-reactive people, cool your jets, it’s okay). If you’ve been wondering what this whole reactive thing is, here’s another chance to learn.
  • Speaking of learning: “Monads: It’s OK to Feel Stupid” punts on the idea of describing what a monad is, saying that it’s okay if you don’t understand them – you can use them anyway. (Java’s streams provide a lot of access to functionality through monads, which present “computations represented as sequences of steps.”)
  • The 5 Golden Rules of Giving Awesome Customer Support” goes through some basic things to think about for, of all things, customer support. (Surprise!) The things are topics, not good headings, but one thing they didn’t point out was that people who use your open source software library are customers, too. You’ll want to read the article to get more relevance out of the headings. The points are:
    • All users are customers
    • Your customer took the time
    • Your customer is abrasive and demanding
    • Your customer doesn’t understand your product
    • Your customer doesn’t care about your workflows

Link: The reason to use a buffered stream in Java

The use of buffered streams in Java has come up a few times on ##java recently, so it might be worth reading something that one of the channel residents wrote up about the topic late last year: “The reason to use a buffered stream in Java.”
Aside from being generally useful information, it actually has a test; the conclusion is that using a buffered stream is usually wise because it helps avoid system calls. The test shows this by spending four minutes making system calls, and only one and a half minutes in the actual program code.
Well done.

Combining two functions into one

Every now and then, you may want to apply one function to only some of the elements in your stream.
This is not so much an example of manipulating streams but rather of combining two functions into one with a predicated dictating which function to apply. In concrete terms, we will create a stream of the integers in the range 0 through 10 (non-inclusive), multiply the even numbers by two and add one, then finally display the result.
The first function, or IntUnaryOperator – as it takes and returns one int – (slightly contrived use of andThen and compose) – looks like this:

IntUnaryOperator f = IntUnaryOperator.identity()
   .andThen(i -> i + 1)
   .compose(i -> 2 * i);

The second function is just the identity:

IntUnaryOperator g = IntUnaryOperator.identity();

The predicate, or just a function taking an int and returning a boolean, was to do something for the even integers:

IntPredicate p = (i -> i % 2 == 0);

One way of combining the two functions is close to the lines of “if the value is this, do that to the value and return it, else do something else to the value and return it:”

IntUnaryOperator m = (i -> (p.test(i)
   ? f.applyAsInt(i)
   : g.applyAsInt(i)));

So now we can map the integers by

IntStream.range(0, 10)

However, instead of creating a function taking and returning an integer we could create a function taking an integer and returning a function (which then take and return an integer):

IntFunction<IntUnaryOperator> mm = (i -> p.test(i) ? f : g);

This looks a bit nicer, but applying it to the stream gets messy:

IntStream.range(0, 10)
    .map(i -> mm.apply(i).applyAsInt(i))

It might make be more sensible to just skip the intermediate step and write:

IntStream.range(0, 10)
    .map(i -> (p.test(i) ? f : g)

.. which is also a way to get around the problem of prepending or appending the functions f or g:

IntStream.range(0, 10)
    .map(i -> (p.test(i) ? f : g.andThen(j -> j + 100))

Caveat lector: There are probably much cleaner and more sensible ways to do this. Feel free to suggest alternatives!