JavaZone 2016

It's been a while since I wrote a conference write up. The short version of "why" is because I got a bit bored of doing it. Plus, I found I was attending conferences as a speaker "on the circuit", and my experience of hanging out, catching up with my friends, chatting to other attendees to see what they're up to and so forth, didn't seem as useful to share with people who might want to find out whether a conference is worth attending from a content or atmosphere point of view.

But I feel compelled to blog about JavaZone. I presented there back in 2013, but every year since then haven't made it for one reason or another (the fact that it's near my birthday in no way impacts my scheduling…). I made the effort this year, and I'm so pleased. Now I've been to many more conferences, of various sizes, various themes, all around the world, and I can definitely state that JavaZone is up there as one of the best conferences around.

Why?

Continue reading "JavaZone 2016"

Java 8 MOOC – Session 3 Summary

Last night was the final get-together to discuss the Java 8 MOOC. Any event hosted in August in a city that is regularly over 40°C is going to face challenges, so it was great that we had attendees from earlier sessions plus new people too.

<img src="https://trishagee.github.io/static/images/java8mooc/lesson3.jpg&#34; alt="Woohoo lambdas!" title="Woohoo lambdas!">

The aim of this session was to talk about Lesson 3, but also to wrap up the course as a whole: to talk about what we liked and what we would have improved (about both the course itself and our user group events).

As in the previous two posts, let’s outline our discussion areas:

findAny() vs findFirst(): Why do we need both of these methods, and when would you use them?

Well, findFirst() is the deterministic version, which will return you the first element in the Stream (according to encounter order - see the section on Ordering in the documentation). So, regardless of whether you run the operation in parallel or serial, if you’re looking for “A” and use findFirst with this list:

["B", "Z", "C", "A", "L", "K", "A", "H"] 

you’ll get the element at index 3 - the first “A” in the list.

But findAny() is non-deterministic, so will return you any element that matches your criteria - it could return the element at index 3, or the one at position 6. Realistically, if the stream is on an ordered collection like a list, when you run findAny on a sequential stream, I expect it will return the same result as findFirst. The real use-case for findAny is when you’re running this on a parallel stream. Let’s take the above list, and assume that when you run this on a parallel stream it’s processed by two separate threads:

["B", "Z", "C", "A",    // processed by thread 1   "L", "K", "A", "H"]     // processed by thread 2 

It’s possible that thread 2 finds its “A” (the one at position 6) before thread 1 finds the one at position 3, so this will be value that’s returned. By configuring the Stream to return any one of the values that matches the criteria, you can potentially execute the operation faster when running in parallel.

If findAny is (potentially) faster in parallel and (probably) returns the same value as findFirst when running in serial, why not use that all the time? Well, there are times when you really do want the first item. If you have a list of DVDs ordered by year the film was released, and you want to find the original “King Kong” (for example), you’ll want findFirst to find the one released in 1933, not the one that was released in 1976 or the one from 2005.

Plus, findFirst is not always going to be slower than findAny, even in parallel. Going back to our list:

["B", "Z", "C", "A", "L", "K", "A", "H"] 

Trying to findFirst or findAny for “H” could be the same performance for both methods.

Collectors: Maybe it’s just me who doesn’t really see the big picture for collectors. I’m perfectly content with the built in collectors like:

collect(Collectors.toList()) 

and

collect(Collectors.toSet()) 

It’s easy to see what they do, and work out when you need to use them.

I’m also very happy to have discovered joining:

collect(Collectors.joining(",")) 

a super-useful way to create Comma Separated Values (CSVs) that I use in my Java 8 demo.

Where things get a bit murky for me is where we start chaining up collectors:

collect(Collectors.mapping(...).combiner().andThen(...).apply(...)) 

(it should be obvious from my lack of clear example that I’m not 100% certain under which circumstances these are useful).

As a group, we think the chained collectors are kinda ugly - not because we’re against chaining (we like Streams), but maybe because it’s another chain inside a param to a chain.

We think this is an area where some good, solid examples and a bit of daily use will make it much clearer to developers. We hope.

Related to this, the course didn’t go into creating your own collectors at all. My personal (under-informed) opinion is that I guess most developers should be able to use either the out-of-the-box collectors (toList etc) or use the collector chaining to build what they need. If you need a custom collector, perhaps you haven’t considered everything that’s already available to you. But as a group, we decided we would have liked to see this topic anyway so that we could get a deeper understanding of what collectors are and how they work.

Exercises for lesson 3: Well. What can we say? I really hope there are people reading this who haven’t finished the course yet, because the Sevilla Java User group would like to say to you: don’t despair, the lesson 3 exercises are substantially harder than those for lessons 1 and 2. Honestly, the whole group considered it less of a learning curve and more of a massive cliff to climb.

I have no idea what I am doing

I mean, it was great to have something so challenging to end on, but it probably would have been less ego-destroying if we could have got up to that level gradually instead of having it sprung on us.

The good thing about Part 2 of the lesson 3 exercises was that we had three very different answers to discuss in the group. None of us were super happy with any of them, but we could see definite pros and cons of each approach, and that’s something you really want to learn in a course like this.

It was also really great to have a rough performance test to run on your own computer, so that you could really see the impact of your choices on the performance of the stream.

For more info
I’m going to add a shameless plug to a friend’s book here. I’ve been reading a lot about Java 8 for this course, for my Java 8 demo, and to generally get up to speed. My favourite book for getting to grips with lambdas and streams is Java 8 Lambdas: Pragmatic Functional Programming by Richard Warburton. This book also contains more info about collectors too, so maybe some of our questions around how to use these in more complex situation are answered in here.

In Summary
We really enjoyed the MOOC, and the sessions to get together to discuss it. We particularly liked that the meetups were a safe place to ask questions and discuss alternative solutions, and that we weren’t expected to be genius-level experts in order to participate fully.

If/when Oracle re-runs the MOOC, if you didn’t get a chance to take part this time I highly recommend signing up. And if you can find (or run) a local meetup to discuss it, it makes the experience much more fun.

Java 8 MOOC – Session 2 Summary

As I mentioned last week, the Sevilla Java User Group is working towards completing the Java 8 MOOC on lambdas and streams. We’re running three sessions to share knowledge between people who are doing the course.

The second week’s lesson was about Streams - how you can use the new stream API to transform data. There was also a whole section on Optional, which initially seemed like rather a lot, but it turns out that Optional can do rather more than I originally thought.

In the meetup session, we talked about:
Optional: we were pretty comfortable, I think, with using Optional to prevent a NullPointerException. What we weren’t so clear on were the examples of filter() and map() - if you were getting your Optional values from a stream, why wouldn’t you do the map and the filter on the stream first? For example, why do this:

list.stream()     .findFirst()     .map(String::trim)     .filter(s -> s.length() > 0)     .ifPresent(System.out::println); 

when you could map and filter in the stream to get the first non-empty value? That certainly seems like an interesting question in relation to streams.

I can see Optional being more useful when other APIs fully support Java 8 and return Optional values, then you can perform additional operations on return values.

That terminal operation’s not actually terminal??: We ran into this a couple of times in our examples in the session, one example is the code above (let’s copy it down here so we can look at it more closely):

list.stream()     .findFirst()     .map(String::trim)     .filter(s1 -> s1.length() > 0)     .ifPresent(System.out::println); 

Isn’t findFirst() a terminal operation? How can you carry on doing more operations on that?

The answer is, of course, that the return type of the terminal operation can also lead to further operations. The above is actually:

Optional<String> result = list.stream()                               .findFirst(); result.map(String::trim)       .filter(s1 -> s1.length() > 0)       .ifPresent(System.out::println); 

Our terminal operation returns an optional, which allows you to do further operations. Another example of this confusion:

list.stream()     .map(String::toLowerCase)     .collect(toList())     .forEach(System.out::println); 

Here, collect() is a terminal operation, but it returns a list, which also allows forEach():

List<String> results = list.stream()                            .map(String::toLowerCase)                            .collect(toList()); results.forEach(System.out::println); 

So be aware that just because it’s called a terminal operation, doesn’t mean you can’t perform other operations on the returned value.

Parallel/sequential/parallel: there had been a question in the previous week about why you could write code like this:

list.stream()     .parallel()     .map(String::trim)     .sequential()     .filter(s1 -> s1.length() > 0)     .parallel()     .forEach(System.out::println); 

and whether that would let you dictate which sections of the stream were parallel and which were to be processed in serial. Lesson two set the lesson straight, declaring “the last operator wins” - meaning all of the above code will be run as a parallel stream. I can’t find any documentation for this, I’ll edit this post if I locate it.

Unordered: “Why would you ever want your stream to be unordered?” - the answer is that unordered() doesn’t turn your sorted collection into one with no order, it just says that when this code is executed, the order of elements doesn’t matter. This might make processing faster on a parallel stream, but as a group we figured it would probably be pointless on a sequential stream.

Efficiency optimisations and order of stream operations: We had a long conversation about the order in which you perform operations in a stream. The MOOC (in fact, most documentation around Streams) tells us that a) streams are lazy, and not evaluated until a terminal operator is encountered and b) this enables optimisation of the operations in the stream. That lead to a discussion about the following code:

list.stream()     .map(String::toLowerCase)     .filter(s -> s.length() % 2 == 1)     .collect(toList()); 

The filter operation should result in less items to process in the stream. Given that the map() operation doesn’t change anything that filter() relies on, will this code be optimised somehow under the covers so that the filter is actually executed first? Or are optimisations still going to respect the order of operations on a stream?

Our case is actually a very specific case, because a) the map() returns the same type as the params passed in (i.e. it doesn’t map a String to an int) and b) the map() doesn’t change the characteristic the filter() is looking at (i.e. length). But generally speaking, you can’t expect these conditions to be true - in fact I bet in a large number of cases they are not true. So pipeline operations are performed in the order in which they are written, meaning that our map and filter will not be re-ordered into a more efficient order.

A good rule of thumb seems to be to do filtering as early in the stream as possible - that way you can potentially cut down the number of items you process in each step of the stream. Therefore our code would probably be better as:

list.stream()     .filter(s -> s.length() % 2 == 1)     .map(String::toLowerCase)     .collect(toList()); 

**Flat Map**: what...? [flatMap()](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#flatMap-java.util.function.Function-) is one of those methods that makes total sense once you get the hang of it, and you don't understand why it was so confusing. But the first time you encounter it, it's confusing - how is flatMap() different to map()?

Well, flatMap is used to squish (for example) a stream of streams into just a simple stream. It’s like turning a 2-dimensional array into a single dimension so that you can iterate over all the items without needing nested for-loops. There’s an example on StackOverflow, and some more examples in answer to this question.

Comparators: We’ve probably all written comparators at some point, it’s probably one of those examples where we really did use anonymous inner classes “in the olden days” and were looking forward to replacing them with lambdas.

reader.lines()       .sorted(new Comparator<String>() {           @Override           public int compare(String o1, String o2) {               return ???;           }       })       .collect(toList()); 

Sadly, using a lambda still doesn’t answer the question “do I minus o1 from o2, or o2 from o1?":

reader.lines()       .sorted((o1, o2) -> ??? )       .collect(toList()); 

But there’s yet another new method in Java 8 here that can save us, one that is not nearly as well publicised as it should be. There’s a Comparator.comparing() that you can use to really easily define what to compare on. The JavaDoc and signature looks kinda confusing, but this is one of those places where method references suddenly make loads of sense:

reader.lines()       .sorted(comparingInt(String::length))       .collect(toList()); 

(Here we’re actually using the comparingInt method as we’re going to compare on a primitive value). Personally this is one of my favourite new features in Java 8.

Join us next week for the [last session on Java 8 - Lambdas and Streams](http://www.meetup.com/SVQJUG/events/223910762/).

Android Xtended

You may have noticed that the more I go to conferences, the less I write about them. I could claim lack of time, but the fact is that all my write-ups will be something along the lines of "Loved <city>, went to talks that made me think, met interesting people, gave a talk or two that seemed to go well". Not sure if people get bored of reading that, but I get bored of writing it.

That's not to say I'm bored of conferences. On the contrary - since I work from home, travelling to new places and meeting Real Human Beings keeps me sane. Plus conferences are fun.

But I went to a conference on Saturday that makes me feel compelled to write something, and not just because it was organised by my two fellow Sevilla JUG organisers. @IsraKaos and @RGDav are both doing more Android day-to-day than server-side Java, so this is an area they're interested in learning more about. Not content with organising Android events every other month, they decided they had so many interesting speakers they wanted to have speaking here in Sevilla that they wanted to run a whole day, single track conference, on behalf of GDG Sevilla. Android Xtended was born.

Continue reading "Android Xtended"

SVQ JUG: The State of Java

I think living in a beautiful city in a fantastic climate has its advantages. Not just the obvious ones, but we find people unusually keen to come and visit us on the pretence of presenting at the Sevilla Java User Group (and please, DO come and present at our JUG, we love visitors).

This week we were really lucky, we had Georges Saab and Aurelio Garcia-Ribeyro giving us an update on where Java is now and where it looks like it's going in the future.

Continue reading "SVQ JUG: The State of Java"

MongoDB London

<em>TL;DR MongoDB London, 6th November, 50% off with discount code 50Trisha.

So, MongoDB London is nearly upon us again, and I’m dead disappointed I can’t make it this year (I’m [keynoting at GOTO Berlin] (http://gotocon.com/berlin-2014/presentation/Party%20Keynote:%20Staying%20Ahead%20of%20the%20Curve) instead, which I’m terrified, I mean, excited, about). The last MongoDB London was really interesting for me - I was fairly new to the company, I’d been here less than six months, and it was a really great way to go both broad and deep on the technology.

I was trying to find a blog post where I talked about my experiences, but it looks like I only wrote that In My Mind. In fact, I only only wrote two whole lines of notes on the conference. But 18 months later I clearly remember presentations from my colleagues Ross and Derick demonstrating the geo capabilities in MongoDB, presentations which heavily influenced the live coding demo I’ve been giving recently.

I also remember Eliot’s presentation - Eliot is one of those people who totally gets away with breaking the “speak in a measured, clear fashion” presenters rule, he fires fascinating information at you at high speed and it’s actually one of the compelling things about his talks. If you ever get a chance to see him talk about the product, it’s totally worth it.

Other than that, the most awesome thing about the conference was the chance to meet, and talk to, a bunch of different MongoDB people - there are the engineers who work on the product (like me and my colleagues); the people leading the way with the technology, like Eliot; and finally, but for me most importantly, you get to meet really interesting people who are using MongoDB in ways that you might not even imagine.

Anyway the point of this sales pitch is, whether you’re using MongoDB already or you’re keen to find out about it, MongoDB London is only going to take a day from your life, and you’ll learn a bunch of interesting things. And, with a Special Discount Code from me, it’s only £45! Sign up with code 50Trisha.

What could possibly go wrong? (GOTO Chicago)

At GOTO Chicago, I was given the chance to chat a bit about the presentation I was giving, which happens to be the same one I’m giving at a number of conferences this year (although of course I’m evolving it as I go along).

The presentation leaves very little time for anything other than coding, as it’s quite challenging to create a full app in 50 minutes, so it was great to have the chance to talk about the motivations for the demo

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"> <iframe src="https://www.youtube.com/embed/sZee7lRAUF4&#34; style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">

The video of the actual talk is also available now:

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"> <iframe src="https://www.youtube.com/embed/kmVnhyWqozA&#34; style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">