### Java 8 Friday

Every Friday, we’re showing you a couple of nice new tutorial-style Java 8 features, which take advantage of lambda expressions, extension methods, and other great stuff. You’ll find the source code on GitHub.### Java 8 Goodie: Easy-as-Pie Local Caching

Now get ready for one of the most awesome revelations in this series so far. We’ll show you an easy-as-pie way to implement a local cache using the good old`HashMap`

and lambda expressions. Because, `Map`

now has a new way of a atomically calculating a new value in case a key is absent. Perfect for caches. Let’s delve into code:
```
public static void main(String[] args) {
for (int i = 0; i < 10; i++)
System.out.println(
"f(" + i + ") = " + fibonacci(i));
}
static int fibonacci(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
System.out.println("Calculating f(" + i + ")");
return fibonacci(i - 2) + fibonacci(i - 1);
}
```

`fibonacci(5)`

, the above algorithm will print out a huge amount of lines, as we’re repeating the same calculations exponentially:
Calculating f(6) Calculating f(4) Calculating f(2) Calculating f(3) Calculating f(2) Calculating f(5) Calculating f(3) Calculating f(2) Calculating f(4) Calculating f(2) Calculating f(3) Calculating f(2) f(6) = 8What we want to do is build a cache of previously calculated fibonacci numbers. The most straightforward technique is to memoize all values in a cache. Here’s how we build a cache:

```
static Map<Integer, Integer> cache = new HashMap<>();
```

Done! As mentioned before, we’re using the newly addedImportant side note: A previous version of the blog post used a`ConcurrentHashMap`

here. DO NOT USE ConcurrentHashMaps when you recursively calculate values using`computeIfAbsent()`

. Details here: http://stackoverflow.com/q/28840047/521799

`Map.computeIfAbsent()`

method to calculate a new value from a `source`

function only if we don’t already have a value for a given key. Caching! And since this method is guaranteed to execute atomically, `ConcurrentHashMap`

, this cache is even thread-safe without resorting to manually applying `synchronized`

anywhere`fibonacci()`

function.
```
static int fibonacci(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
return cache.computeIfAbsent(i, (key) ->
fibonacci(i - 2)
+ fibonacci(i - 1));
}
```

```
static int fibonacci(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
return cache.computeIfAbsent(i, (key) -> {
System.out.println(
"Slow calculation of " + key);
return fibonacci(i - 2) + fibonacci(i - 1);
});
}
```

f(0) = 0 f(1) = 1 Slow calculation of 2 f(2) = 1 Slow calculation of 3 f(3) = 2 Slow calculation of 4 f(4) = 3 Slow calculation of 5 f(5) = 5 Slow calculation of 6 f(6) = 8 Slow calculation of 7 f(7) = 13 Slow calculation of 8 f(8) = 21 Slow calculation of 9 f(9) = 34

### How would we have done it in Java 7?

Good question. With lots of code. We’d probably write something like this using double-checked locking:```
static int fibonacciJava7(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
Integer result = cache.get(i);
if (result == null) {
synchronized (cache) {
result = cache.get(i);
if (result == null) {
System.out.println(
"Slow calculation of " + i);
result = fibonacci(i - 2)
+ fibonacci(i - 1);
cache.put(i, result);
}
}
}
return result;
}
```

*actual*solution would probably make use of Guava Caches.

### Conclusion

Lambdas are only one part of Java 8. An important part, but let’s not forget all the new features that were added to the libraries and that can be leveraged with lambdas now! This is really exciting and…We can greatly improve our code bases without resorting to new libraries. All of the above can be run with the JDK’s libraries only.Next week in this blog series, we’re going to look at how Java 8 will improve on the existing and new concurrency APIs, so stay tuned!