Java 8

3 posts

Java 8 magic with method references

When you start learning a new programming language you often encounter snippets of code which you have no idea why they work. The more you learn about that programming language to more you understand and these moments become rare.

Today, after programming many years in Java, I ran into such a situation with Java 8 and was really fascinated about it.

It all started with the problem of having a Stream<T> and wanting to “for-each” iterate over its content. The for-each construct in Java requires to have an array or Iterable<T>. However Stream<T> does only provide an Iterator<T>, which is not the same.

Now there are many solutions (good and bad) out there for this problem. However one solution really fascinated me:

[code language=”java”]
Stream<String> s = …;

for (String v : (Iterable<String>) s::iterator) {

}
[/code]

Now wait … Stream<T> does have a method iterator which returns an Iterator<T>. But Iterator<T> cannot be cast to Iterable<T>! And also is “s::iterator” not calling the method, but referencing the method.

Screenshot of Eclipse Quick Fix for Lambda expressions

Pasting this code fragment into the Eclipse IDE helps to understand what actually happens. Pressing Ctrl+1 on a code fragment allows to convert method references to lambda expressions and lambda expressions to anonymous classes. Quite fantastic ;-)

So, lets see how this code fragment get expanded to a lambda expression:

[code language=”java”]
for ( final String v : (Iterable<String>)() -> s.iterator () ) {

}
[/code]

And this lambda expression is equivalent to:

[code language=”java”]
for ( final String v : new Iterable<String> () {
public Iterator<String> iterator () {
return s.iterator ();
}} ) {

}
[/code]

The last snippet is rather bloated, as inner classes have always been in Java.

The magic which is happening is done by Java 8 new features “method references” and the “functional interfaces”. A functional interface is a java interface which only has one method to implement. “default” methods don’t count. Looking at Iterable<T> this is the case. So an Iterable<T> can be implemented with a lambda expression and or method reference. But for the for-each loop, Java does not “know” what you have mind. This is where the cast comes into play. By casting the method reference to Iterable<T>, Java infers that an Iterable<T> is requires, which can be provided by the method reference to Iterator<T>.

But looking at Iterable<T> there is no @FunctionalInterface present?!

That is right. But @FunctionalInterface is not a requirement for actually being a functional interface. It only tells the compiler to fail if the interface is not. So the downside of this example is, that there is no guarantee that Iterable<T> will always stay a functional interface, since the authors have not committed to that using @FunctionalInterface.

In the end, I am not sure if this is a good solution for my original problem. But is still is a fascinating piece of code and a great idea indeed.

Java 8 streaming – or not?

One of the most advertised use cases of the new lambdas in Java 8 is the possibility to stream collections and transform it. The “series of tubes” has a lot of examples on how to do this, I just wanted to look at it from a different perspective, readability.

So starting with a real-life problem of a map Map<ResultKey, List> result which I want to transform into a Set<String>.

Before Java 8, I had something like:

[code language=”java”]
Set<String> ids = new HashSet<> ();
for ( List<ResultEntry> list : result.values () ) {
for ( ResultEntry entry : list ) {
if ( entry.getAction () == Action.DELETE ) {
String id = entry.getArtifact ().getId ();
ids.add ( id );
}
}
}
[/code]

Now, with Java 8, I can do:

[code language=”java”]
Set<String> deleteSet = result.values ().stream ()
.flatMap ( list -> list.stream () )
.filter ( entry -> entry.getAction () == Action.DELETE )
.map ( entry -> entry.getArtifact ().getId () )
.collect ( Collectors.toSet () );
context.deleteArtifacts ( deleteSet );
[/code]

Neither one is shorter nor seems less complex from an initial view. So, which one is better?

A bit of Java 8 Optional<T>

For me Java 8 wasn’t a big deal … until I had to go back to Java 7. Suddenly I started missing things I started using without even realizing it. Here comes Optional<T>:

Assume we have some sort of class (Provider) which does something and has a “getName” method. Now we also have a method in a class managing providers which returns the provider by id, so we pass in a string ID and get back a provider:

[code language=”Java”]
static class Provider {
String getName () {
return "bar";
}
}

static Provider getProvider ( final String id ) {
if ( "foo".equals ( id ) ) {
return new Provider ();
}
return null;
}
[/code]

In this simple example the manager only knows the provider “foo”, which will return “bar” as its name. All requests for other providers will return null. A real life scenario might have a Map, which also returns null in case of a missing element.

Now a pretty common code snippet before Java 8 would look like this:

[code language=”Java”]
final Provider provider = getProvider ( "bar" );
final String value;
if ( provider != null ) {
value = provider.getName ();
} else {
value = null;
}
System.out.println ( "Bar (pre8): " + value );
[/code]

Pretty noisy. So the first step is to use the “Optional” type, and to guarantee that the getProvider method never returns null. So we don’t have to check for it:

[code language=”Java”]
static Optional<Provider> getOptionalProvider ( final String id ) {
return Optional.ofNullable ( getProvider ( id ) );
}
[/code]

In this case a new method was added, which simply calls the old one. The next thing is to use Optional.map(…) and Optional.orElse(…) to transform the value and return a default if we don’t have a value.

[code language=”Java”]
String value1 = getOptionalProvider ( "foo" )
.map ( Provider::getName )
.orElse ( null );
System.out.println ( "Foo: " + value1 );
[/code]

Pretty simple actually. But still readable and understandable (although some people might disagree on that one ;-) ).

So what does happen? First the call to getOptionalProvider will now never return null. If the value itself would be null, it would return an empty Optional but still a class instance. Actually always the same, since there is only one instance of an empty Optional. Next the map method will call the provided expression (longer version would be: value -> value.getName()), but the method will only do this if the Optional is not empty. Otherwise it will return an empty Optional again. So after calling map we either have an Optional<String> with the value of getName(), or again an empty Optional. Calling orElse on this new Optional will either return the value of the Optional or the default value provided, null in this case.

Of course one could argue that internally the same logic happens as with Java 7 and before. But I think that this way, you actually can do a one-liner which is understandable but still does not obstruct the your actual class with to many lines of code just or checking about null.

Continue reading