Not my cup of mud

Java 8: Let’s deprecate those legacy libs

Lukas Eder
grouch

Much to the delight of ‘Dr Deprecator’, JDK enhancements mean that we can throw out a whole bunch of junk. Lukas Eder sifts out his personal choices for the trash heap.

This post was originally published over at jooq.org as part of a special series
focusing on all things Java 8, including how take advantage of
lambda expressions, extension methods, and other great
stuff. You’ll find the
source code on GitHub
.

Apart from Lambdas and extension methods, the JDK has also
been enhanced with a lot of new library code, e.g. the Streams API
and much more. This means that we can critically review our stacks
and – to the great joy of 
Doctor
Deprecator
 – throw out all the garbage that we no
longer need.

Here are a couple of them, just to name a few:

LINQ-style libraries

There are lots of libraries that try to emulate LINQ (i.e. the
LINQ-to-Collections part). We’ve
already made our point before, because we now have the awesome Java
8 Streams API
. 5 years from today, no Java developer will be
missing LINQ any longer, and we’ll all be Streams-masters
with Oracle Certified
Streams Developer
 certifications hanging up our walls.

Don’t get me wrong. This isn’t about LINQ or Streams being
better. They’re pretty much the same. But since we now have Streams
in the JDK, why worry about LINQ? Besides, the SQLesque syntax for
collection querying was misleading anyway. SQL
itself is much more than Streams will ever be (or needs to
be)
.

So let’s list a couple of LINQesque APIs, which we’ll no longer
need:

LambdaJ

This was a fun attempt at emulating closures in Java through
arcane and nasty tricks like ThreadLocal.
Consider the following code snippet (taken from
here
):

// This lets you "close over" the
// System.out.println method
Closure println = closure(); {
  of(System.out).println(var(String.class));
}
 
// in order to use it like so:
println.apply("one");
println.each("one", "two", "three");

Nice idea, although that semi-colon after closure(); and before
that pseudo-closure-implementation block, which is not really a
closure body… all of that seems quite quirky ;-)

Now, we’ll write:

Consumer<String> println = System.out::println;
 
println.accept("one");
Stream.of("one", "two", "three").forEach(println);

No magic here, just plain Java 8.

Let’s hear it one last time for Mario
Fusco
 and Lambdaj.

Linq4j

Apparently, this is still being developed actively… Why? Do note
that the roadmap also has a LINQ-to-SQL implementation in it,
including:

Parser support. Either modify a Java parser (e.g. OpenJDK), or
write a pre-processor. Generate Java code that includes expression
trees.

Yes, we’d like to have such a parser for jOOQ as well. It would allow us to
truly embed SQL in Java, similar to SQLJ, but
typesafe. But if we have the Streams API, why not implement
something like Streams-to-SQL?

We cannot say farewell to Julian Hyde‘s Linq4j just yet, as
he’s still continuing work. But we believe that he’s investing in
the wrong corner.

Coolection

This is a library with a fun name, and it allows for doing
things like…

from(animals).where("name", eq("Lion"))
             .and("age", eq(2))
             .all();
 
from(animals).where("name", eq("Dog"))
             .or("age", eq(5))
             .all();

But why do it this way, when you can write:

animals.stream()
       .filter(a -> a.name.equals("Lion")
                 && a.age == 2)
       .collect(toList());
 
animals.stream()
       .filter(a -> a.name.equals("Dog")
                 || a.age == 5)
       .collect(toList());

Let’s hear it for Wagner Andrade. And then off
to the bin

Half of Guava

Guava has
been pretty much a dump for all sorts of logic that should have
been in the JDK in the first place. Take com.google.guava.base.Joinerfor
instance. It is used for string-joining:

Joiner joiner = Joiner.on("; ").skipNulls();
. . .
return joiner.join("Harry", null, "Ron", "Hermione");

No need, any more. We can now write:

Stream.of("Harry", null, "Ron", "Hermione")
      .filter(s -> s != null)
      .collect(joining("; "));

Note also that the skipNulls flag and all
sorts of other nice-to-have utilities are no longer necessary as
the Streams API along with lambda expressions allows you to
decouple the joining task from the filtering task very nicely.

Convinced? No?

What about:

And then, there’s the whole set of Functional stuff that can be
thrown to the bin as well:

https://code.google.com/p/guava-libraries/wiki/FunctionalExplained

Of course, once you’ve settled on using Guava throughout your
application, you won’t remove its usage quickly. But on the other
hand, let’s hope that parts of Guava will be deprecated soon, in
favour of an integration with Java 8.

JodaTime

Now, this one is a no-brainer, as the popular JodaTime library got
standardised into the java.time packages.
This is great news.

Let’s hear it for “Joda” Stephen
Colebourne
 and his great work for the JSR-310.

Apache commons-io

The java.nio packages
got even better with new methods that nicely integrate with the
Streams API (or not). One of the main reasons why anyone would have
ever used Apache Commons
IO
 was the fact that it is horribly tedious to read files
prior to Java 7 / 8. I mean, who would’ve enjoyed this piece of
code (from
here
):

try (RandomAccessFile file =
     new RandomAccessFile(filePath, "r")) {
    byte[] bytes = new byte[size];
    file.read(bytes);
    return new String(bytes); // encoding?? ouch!
}

Over this one?

List<String> lines = FileUtils.readLines(file);

But forget the latter. You can now use the new methods
injava.nio.file.Files,
e.g.

List<String> lines = Files.readAllLines(path);

No need for third-party libraries any longer!

Serialisation

Throw it all out, for there is JEP 154 deprecating
serialisation. Well, it wasn’t accepted, but we could’ve surely
removed about 10% of our legacy codebase.

A variety of concurrency APIs and helpers

With JEP
155
, there had been a variety of improvements to concurrent
APIs, e.g. to ConcurrentHashMaps
(we’ve blogged about it before)
, but also the
awesome LongAdders,
about which you can read a nice article over at the Takipi
blog
.

Haven’t I seen a whole com.google.common.util.concurrent package
over at Guava, recently? Probably not needed anymore.

JEP
154
 (Serialisation) wasn’t real

It was an April Fools’ joke, of course…

Base64 encoders

How could this take so long?? In 2003, we’ve had RFC 3548, specifying
Base16, Base32, and Base64 data encodings, which was in fact based
upon base 64 encoding specified in RFC 1521, from
1993, or RFC
2045
from 1996, and if we’re willing to dig further into the
past, I’m sure we’ll find earlier references to this simple idea of
encoding binary data in text form.

Now, in 2014, we finally have JEP
135
 as a part of the JavaSE8, and thus (you wouldn’t
believe it): java.util.Base64.

Off to the trash can with all of these libraries!

… gee, it seems like everyone and their dog worked around this
limitation, prior to the JDK 8…

More?

Provide your suggestions in the comments! We’re curious to hear
your thoughts (with examples!)

Conclusion

As with any Java major release, there is a lot of new stuff that
we have to learn, and that allows us to remove third-party
libraries. This is great, because many good concepts have been
consolidated into the JDK, available on every JVM without external
dependencies.

Disclaimer: Not everything in this article
was meant seriously. Many people have created great pieces of work
in the past. They have been very useful, even if they are somewhat
deprecated now. Keep innovating, guys! :-)

Want to delve more into the many new things Java 8 offers? Go
have a look over at the Baeldung blog, where this excellent list of
Java 8 resources is featured: http://www.baeldung.com/java8

Author
Lukas Eder
Lukas is a Java and SQL aficionado. He’s the founder and head of R&D at Data Geekery GmbH, the company behind jOOQ, the best way to write SQL in Java.
Comments
comments powered by Disqus