Lambda's/Closures in JDK 1.6

Llewellyn Falco isidore at setgame.com
Tue Oct 12 09:38:26 PDT 2010


Java Lambdas <http://blog.approvaltests.com/2010/10/java-lambdas.html>

Lambdas allow for code like:
Query.*orderBy*(people, *new* S1<Person>(a){{ret(a.getAge());}});
Check out the video and download the jar to get started at
http://bit.ly/lambdas


I mentioned last month that I had found a way to add lambdas to the current
JDK. I struck me that perhaps many of you had not used lambdas before, so I
thought I make a small tutorial on one of the common uses:

*Sql like queries against your objects.*
Let’s start with the most basic,

*Order By*
If you where writing an Sql query to get people based on age, you would say

*Select* *
*From* People
*Order By *age

or perhaps

*Select* *
*From* People a
*Order By* a.age

If you had an array of people in *C#* this would be written as

Linq.OrderBy(people, a => a.GetAge())

Now, to do this in Java is a little more compacted, but very similar

Query.*orderBy*(people, *new* S1<Person>(a){{ret(a.getAge());}});

let’s look at some more examples.

*Select*
Let’s say you wanted to get the names of all the people, you’d write a query
like

*Select* a.names
*From* people a

Now, let’s translate that into java

Query.*select*(people, *new* F1<Person, String>(a){{ret(a.getName());}});

of course, with java you can select more than just primitives, if you wanted
the Addresses, you could do that too.

 Query.*select*(people, *new* F1<Person, Address>(a){{ret(a
.getAddress());}});

you can even do transforms

 List<Student> students =
     Query.*select*(people,
        *new* F1<Person, Student>(a){{ret(*new* Student(a.getName(), a
.getAge()));}});



let’s move on.

*Where*
Of course most queries wouldn’t be much use without the where statement.
Let’s find the all the A+ students

Query.*where*(people, *new* F1<Person,Boolean>(a){{ret(a.getGradePoint() >
3.8);}})

btw: it might be worth expanding the code a bit. I’m cheating a little to
help with understanding. For lambdas to work in Java, there is an
unfortunate side effect. It gets call 1 extra time. Specifically the first
time. So you need to pass in an object. That object  in the examples above
is pre-defined as ‘a’ but in practice I usually use a blank object

*new* F1<Person,Boolean>(new Person()){{ret(a.getGradePoint() > 3.8);}}

unfortunately, you can’t use ‘null’ because it would throw a null pointer
exception. I also use the null object pattern a lot: Person.Null
of course there are some standard calculations that are nice too.


*Average*
what if you wanted the average length of a person’s name?
simple
Query.*average*(people, *new* F1<Person, Number>(a){{ret(a
.getName().length());}});

of course for averages, the return type F1<InputType, ReturnType>  must be a
Number.

*Min*
by now you probably see how easy it would be to get a minimum or maximum, so
let’s up the lambda by using a local variable. Let’s find the person who got
the closest grade to sally.

 *final* Person sally = getPersonByName("Sally");
 Query.*min*(people, *new* S1<Person>(a, sally){{
                    ret(Math.*abs*(a.getGradePoint() -
sally.getGradePoint()));}});



You might have noticed the *final *key word, java requires that for locals
to be used inside of the lambdas. you might also have noticed that this time
I had to pass in 2 parameters (a, sally) to use sally inside you need to add
her as a parameter as well. Lastly, I used the class S1<Input> here instead
of F1<Input,ReturnType> this is just a convenience class which extends F1,
since any where, min, or max queries require the output to be a
Comparable object,
like Integer, String etc.



Well, I hope this got you interested in what lambdas can do for you. Check
out the video and download the jar to get started at http://bit.ly/lambdas

Happy coding,
Llewellyn Falco



More information about the coin-dev mailing list