Spice up your code - Konvertera listor
Det är vanligt förekommande att utvecklare behöver skriva kod för att konvertera listor. Listor kan behöva filtreras eller konverteras mellan olika format. Ett vanligt förekommande mönster när en lista ska konverteras är att skapa en ny lista för resultatet, iterera över ett givet data-set, konvertera varje post och lägga det till resultat-listan. Det är inte helt ovanligt att resultatet också filtreras i denna process. Nedan är ett exempel i Java:
Collection<String> c = new ArrayList<String>();
for (Person person : persons) {
if (person.getAge() >= 18) {
c.add(person.getName());
}
}
Ovanstående exempel kan tyckas både enkelt och funktionellt men jämför med hur detta kan lösas i Python:
l = [person.name for person in persons if person.age >= 18]
Alternativt genom att använda filter och lambda kan det också skrivas så här:
l = [person.name for person in filter(lambda person: person.gender >= 18, persons)]
I Java (1-7) finns tyvärr inte motsvarande funktionalitet. Det finns däremot alternativ för att lösa det på ett liknande sätt. Guava är ett projekt och innehåller flera bibliotek som Google använder till sina Java-projekt. Bland annat erbjuder dessa bibliotek funktioner för att filtrera och transformera listor på ett mer ‘funktionellt’ sätt. Nedan är en lösning som löser samma problem som ovan implementerad med hjälp av dessa funktioner:
Function<Person, String> f = new Function<Person, String>() {
@Override
public String apply(Person input) {
return input.getName();
}
};
Predicate<Person> p = new Predicate<Person>() {
@Override
public boolean apply(Person input) {
return input.getAge() >= 18;
}
};
Collection<String> c = Collections2.transform(Collections2.filter(persons, p), f);
Enklare exempel som detta blir möjligtvis varken mer kompakta eller lättlästa. När konverteringar som denna däremot upprepas så blir detta alternativ genast mer attraktivt. Jämför till exempel med JDBC-mappers som inte helt sällan återanvänds. Guava är licensierat under Apache License 2.0 och innehåller flertalet användbara funktioner. Ett alternativ är också Apache Commons, värt att nämna är att Apache Commons för närvarande tyvärr inte stödjer Java generics.
Lägg till följande beroende i din Maven-pom för att testa Guava:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>10.0.1</version>
</dependency>
I väntan på en Java-version (Java 8?) som stödjer closures och lambda-funktioner går det också att använda lambdaj. Med lambdaj kan en lista till exempel konverteras och filtreras på följande sätt:
import static ch.lambdaj.Lambda.*;
import static org.hamcrest.Matchers.*;
...
Collection<String> c = collect(filter(having(on(Person.class).getAge(), greaterThanOrEqualTo(18)), persons), on(Person.class).getName());
Lägg till följande Maven-beroende för att använda lambdaj:
<dependency>
<groupId>com.googlecode.lambdaj</groupId>
<artifactId>lambdaj</artifactId>
<version>2.3.1</version>
</dependency>