Functional programming is all the rage. It can undoubtedly produce cleaner and more expressive code, but why switch to Scala or wait for Java 8? In fact, there are many ways to dramatically improve your Java code quality by using a more functional style today. This presentation discusses how techniques such as functional programming, using fluent APIs, and other clean coding practices can make your code more concise, more readable, and much easier to maintain. But more importantly, you will learn about libraries such as LambdaJ and Google Guava that make this possible today with your existing Java code base.
12. Java
8
supports
Lambda
Expressions
public class Pet {
private String name;
private Species species;
Pet(String name, Species species) {...}
public String getName() {...}
public Species getSpecies() {...}
@Override
public boolean equals(Object o) {...}
@Override
public int hashCode() {...}
enum Species {
Cat,
Dog,
GuineaPig;
Pet called(String name) { return new Pet(name, this); }
}
}
13. Java
8
supports
Lambda
Expressions
public class Pet {
List<Pet> private String name;
pets = Arrays.asList(Cat.called("Ginger"),
private Species species;
Dog.called("Spot"),
GuineaPig.called("Fluffy"),
Pet(String name, Species species) {...}
Dog.called("Rover"));
public String getName() {...}
List<Pet> public Species getSpecies()-> a.getSpecies() == Dog)
sortedDogs = pets.filter(a {...}
.sorted((a, b) -> a.getName().compareTo(b.getName()))
.into(new ArrayList<Pet>());
@Override
public boolean equals(Object o) {...}
assertThat(sortedDogs, contains(Dog.called("Rover"),
@Override Dog.called("Spot")));
public int hashCode() {...}
enum Species {
Cat,
Dog,
GuineaPig;
Pet called(String name) { return new Pet(name, this); }
}
}
23. Immutable
Collec:ons
Creating an immutable list
List<String> colors = ImmutableList.of("red", "green", "blue");
Set<String> colors = ImmutableSet. of("red", "green", "blue");
Set<String> myColors = ImmutableSet.copyOf(colors);
Creating an immutable copy
24. No
more
returning
Null
“Null sucks.”
- Doug Lea
“I call it my billion-dollar mistake.”
- Sir Tony Hoare
25. No
more
returning
Null
What does a null return value mean?
interface ClientService {
Client findByName(String name);
}
No matching client found (but we were expecting one)?
No matching client found (but we’re cool with that)?
Something went wrong?
26. No
more
returning
Null
Sometimes we might not return a client
interface ClientService {
Optional<Client> findByName(String name);
}
This forces us to cater for this case in our code
Optional<Client> clientOptional = clientService.findByName("Smith");
if (clientOptional.isPresent()) {
Client client = clientOptional.get();
} else {
// No client was found
}
27. No
more
returning
Null
A person may not have a favorite color
class Person {
Optional<Color> getFavoriteColor();
}
Color colorToUse = person.getFavoriteColor().or(Blue)
If not, use Blue
29. No
more
returning
Null
What does a null return value mean?
interface ClientService {
Client findByName(String name);
}
No matching client found (but we were expecting one)?
No matching client found (but we’re cool with that)?
Something went wrong?
30. No
more
returning
Null
Sometimes we might not return a client
interface ClientService {
Optional<Client> findByName(String name);
}
This forces us to cater for this case in our code
Optional<Client> clientOptional = clientService.findByName("Smith");
if (clientOptional.isPresent()) {
Client client = clientOptional.get();
} else {
// No client was found
}
31. No
more
returning
Null
A person may not have a favorite color
class Person {
Optional<Color> getFavoriteColor();
}
Color colorToUse = person.getFavoriteColor().or(Blue)
If not, use Blue
32. lambdaj
– DSL for manipulating collections in a functional style
– Replace loops with more concise and readable code
33. LambdaJ support many high level
collection-related functions
filter aggregate
sort
convert
extract group
48. Checking
existence
in
LambdaJ
[Spot, Rover, Ginger, Fluffy]
exists(pets, having(on(Pet.class).getSpecies(), is(Cat)))
true
49. Using
Predicates
in
LambdaJ
Predicate<Pet> carnivores = (pet) -> (pet.getSpecies() == Dog || pet.getSpecies() == Cat);
List<Pet> carnivorousPets = pets.filter(carnivores).into(new ArrayList<Pet>());
Java 8
Matcher<Pet> carnivore = new Predicate<Pet>() {
public boolean apply(Pet pet) {
return (pet.getSpecies() == Dog || pet.getSpecies() == Cat);
}
};
List<Pet> carnivores = filter(carnivore, pets);
LambdaJ
50. Using
Aggregates
in
LambdaJ
List<Pet> pets = Arrays.asList(Cat.called("Ginger"),
Dog.called("Spot"),
GuineaPig.called("Fluffy"),
Dog.called("Rover")
);
int ageOfOldestPet = maxFrom(pets).getAge();
int ageOfYoungestPet = minFrom(pets).getAge();
int totalPetAges = sumFrom(pets).getAge();
56. Some
real-‐world
examples
Tag
Tag 1
TagProvider1 Tag
TagProvider2 Tag
Tag
Tag
Tag
flatten(extract(TagProviders, on(TagProvider.class).getTags()));
Tag
Tag 1
Tag
Tag
Tag
Tag
Tag
58. Keeping
things
maintainable
“Excessive use of Guava's functional programming idioms can
lead to verbose, confusing, unreadable, and inefficient code.”
- the Guava team
Can also be true of LambdaJ