Monday, 15 June 2009

Poor's man closures in Java

So, you would like to have closures in Java? Just right after you heard about it in Groovy (or in any other functional language that has them).

I say there is a way in Java to mimic closure behavior with collection!

Let's say you have Collection of Person objects. Person object has its own properties: name, discount and employee (Boolean flag). Now you want to double discount of every employee in that Collection. 

I bet it's trivial task for you! One for...each loop and it's done!

But what if you want to do it in a more elegant yet similar to closures way? Look at this solution that utilizes Google Collections library.


Let's try from test:
@Test
public void shouldDoubleDiscountIfEmployee() throws Exception {
// given
List<Person> people = new ArrayList<Person>();
people.add(new Person("John",true,6));

// when
Collection<Person> list = Collections2.transform(people, new DoubleDiscountForEmployees());

// then
Person john = list.iterator().next();
Integer expectedDiscount = 2*6;
Integer actualDiscount = john.getDiscount();
assertEquals(expectedDiscount , actualDiscount);
}

So, what happend here?
  • First we created list of people and added person with name John, who is employee and has discount rate 6
  • Then we transformed that list using transform method of Collections2 Google's class and our DoubleDiscountForEmployees Function class
  • Last thing is to check if everything went as we intended

That line:
Collection<person> list = Collections2.transform(people, new DoubleDiscountForEmployees());
is something like closure because it executes code in DoubleDiscountForEmployees class againts each object in collection. Isn't that similar to closures?

You must be curious what's inside of that class? Well, there isn't anything special about it. Just one method to implement from Function interface.
package com.zubkiewicz.example.poorsmanclosure;

import com.google.common.base.Function;

public class DoubleDiscountForEmployees implements Function<Person, Person> {

public Person apply(Person person) {
//This is code that you would put in 'real' closure
if(person.isEmployee()) doubleDiscount(person);
return person;
}

private void doubleDiscount(Person person) {
person.setDiscount(person.getDiscount()*2);
}
}

This method is called apply and it is executed againts every object in collection. And that's all (tedious work of iterating through collection is done by Google Collections library).

For those of you that want to check it by yourself here is Person class code
package com.zubkiewicz.example.poorsmanclosure;

public class Person {

private String name;
private Boolean employee;
private Integer discount;

public Person(String name, Boolean employee, Integer discount) {
this.name = name;
this.employee = employee;
this.discount = discount;
}

public Boolean isEmployee() {
return employee;
}

public Integer getDiscount() {
return discount;
}

public void setDiscount(Integer discount) {
this.discount = discount;
}

public String getName() {
return name;
}
}
And here are dependencies (all) for maven pom file
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0-rc1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>


I'm aware that it is not a clouser, but for me it's a similar, elegant solution that at the same time is compatible with SOLID principles. I encourage you to use and explore Google Collections library. It has many other powerful features among that on.

1 comment:

  1. you have nice site. thanks for sharing this site. various kinds of ebooks are available here

    http://feboook.blogspot.com

    ReplyDelete