• Share
  • Email
  • Embed
  • Like
  • Private Content
Functional programming in java
 

Functional programming in java

on

  • 7,289 views

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 ...

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.

Statistics

Views

Total Views
7,289
Views on SlideShare
3,973
Embed Views
3,316

Actions

Likes
12
Downloads
155
Comments
0

17 Embeds 3,316

http://weblogs.java.net 2958
https://twitter.com 142
http://wakaleo.com 123
http://www.wakaleo.com 54
http://www.linkedin.com 10
http://www.java.net 10
http://prototrophy15.swaltsu.com 5
http://johnsmart2.rssing.com 4
http://www.javasight.com 2
https://si0.twimg.com 1
http://www.freerss.net 1
http://www.rss4java.com 1
http://127.0.0.1 1
http://webcache.googleusercontent.com 1
http://cloud.feedly.com 1
http://digg.com 1
http://www.hanrss.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Functional programming in java Functional programming in java Presentation Transcript

    • Improve Your Java Code, Functional-Style - Now! John  Ferguson  Smart john.smart@wakaleo.com  h2p://www.wakaleo.com Twi2er:  wakaleo
    • So who is this guy, anyway? Consulta nt Trainer Mentor Author Speaker Coder John Fer guson S mar t
    • f(x,y) = x + yFunc:onal  Programming  is  the  new  black
    • Immutability  is  your  friend
    • Avoid  nasty  side-­‐effects
    • Benefit  from  concurrency
    • No  more  messy  loops
    • HowWhat
    • Func:onal  Programming  in  Java Coming  to  a  JVM  near  you  the  summer  of  2013
    • Java  8  supports  Lambda  ExpressionsList<String> names = Arrays.asList("Aristotle", "Plato", "Socrates", "Pythagoras");List<String> filteredNames = names       .filter(name -> name.startsWith("P"))       .into(new ArrayList<String>());assertThat(filteredNames, contains("Plato", "Pythagoras"));
    • Java  8  supports  Lambda  Expressions["Aristotle", "Plato", "Socrates", "Pythagoras"] names.filter(name -> name.startsWith("P"))      .into(new ArrayList<String>()); ["Plato", "Pythagoras"]
    • Java  8  supports  Lambda  Expressionspublic 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); }    }}
    • 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); }     } }
    • Java  8  supports  Lambda  Expressions [Ginger, Spot, Fluffy, Rover]pets.filter(a -> a.getSpecies() == Dog)    .sorted((a, b) -> a.getName().compareTo(b.getName()))    .into(new ArrayList<Pet>()); [Rover, Spot]
    • Java  8  supports  Lambda  Expressions [Ginger, Spot, Fluffy, Rover]pets.filter(a -> a.getSpecies() == Dog) .map(e -> { return e.getName(); }) .sorted((a, b) -> a.compareTo(b))    .into(new ArrayList<Pet>()); ["Rover", "Spot"]
    • Java  8  supports  Lambda  Expressions [Ginger, Spot, Fluffy, Rover]Predicate<Pet> carnivores = (pet) -> (pet.getSpecies() == Dog || pet.getSpecies() == Cat);List<Pet> carnivorousPets = pets.filter(carnivores).into(new ArrayList<Pet>()); ["Ginger", "Spot", "Rover"]
    • Java  8  supports  Lambda  Expressions [Ginger, Spot, Fluffy, Rover]pets.filter((pet) -> (pet.getSpecies() == Dog || pet.getSpecies() == Cat))    .into(new ArrayList<Pet>()); ["Ginger", "Spot", "Rover"]
    • Java  8  supports  Lambda  Expressionspublic class VetStay {    private Pet pet;    private Date startOfStay;    private String diagnosis;    public VetStay(Pet pet, Date startOfStay, String diagnosis) {        this.pet = pet;        this.startOfStay = startOfStay;        this.diagnosis = diagnosis;    }} List<VetStay> vetStays = pets.map(pet -> { return new VetStay(pet, new Date(), "sore paw");})                              .into(new ArrayList<VetStay>());
    • Java  8  supports  Lambda  ExpressionsList<Pet> pets = Arrays.asList(Cat.called("Ginger"),        Dog.called("Spot"),        GuineaPig.called("Fluffy"),        Dog.called("Rover"));assert pets.anyMatch(pet -> pet.getSpecies() == Dog)
    • But  Func:onal  Programming  in  Java  today?Surely  this  is  madness!
    • Google Guava
    • Immutable  Collec:onsDefensiveThread-safeEfficient
    • Immutable  Collec:ons Creating an immutable listList<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
    • No  more  returning  Null“Null sucks.” - Doug Lea“I call it my billion-dollar mistake.” - Sir Tony Hoare
    • 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?
    • 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 codeOptional<Client> clientOptional = clientService.findByName("Smith");if (clientOptional.isPresent()) {    Client client = clientOptional.get();} else {    // No client was found}
    • 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
    • And  lots  of  other  stuff...
    • 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?
    • 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 codeOptional<Client> clientOptional = clientService.findByName("Smith");if (clientOptional.isPresent()) {    Client client = clientOptional.get();} else {    // No client was found}
    • 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
    • lambdaj– DSL for manipulating collections in a functional style– Replace loops with more concise and readable code
    • LambdaJ support many high levelcollection-related functions filter aggregate sort convertextract group
    • Filtering  in  LambdaJimport static ch.lambdaj.Lambda.filter;import static org.hamcrest.Matchers.startsWith;...List<String> names = Arrays.asList("Aristotle", "Plato", "Socrates", "Pythagoras");List<String> filteredNames = filter(startsWith("P"), names);assertThat(filteredNames, contains("Plato", "Pythagoras")); LambdaJ Hamcrest
    • Filtering  in  LambdaJ["Aristotle", "Plato", "Socrates", "Pythagoras"] filter(startsWith("P"), names) ["Plato", "Pythagoras"]
    • Filtering  in  LambdaJList<String> filteredNames = new ArrayList<>();for(String name : names) {    if (name.startsWith("P")) {        filteredNames.add(name);    }} Old-style Java names.filter(name -> name.startsWith("P"))      .into(new ArrayList<String>()); Java 8 filter(startsWith("P"), names) Lambda J
    • Filtering  in  LambdaJList<Pet> pets = Arrays.asList(Cat.called("Ginger"),         Dog.called("Spot"),        GuineaPig.called("Fluffy"),         Dog.called("Rover"));List<Pet> sortedDogs = filter(having(on(Pet.class).getSpecies(), is(Dog)), pets);assertThat(sortedDogs, contains(Dog.called("Rover"), Dog.called("Spot")));
    • Filtering  in  LambdaJ [Ginger, Spot, Fluffy, Rover]filter(having(on(Pet.class).getSpecies(), is(Dog)), pets); [Rover, Spot]
    • Sor:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]sort(sortedDogs, on(Pet.class).getName()); [Fluffy, Ginger, Rover, Spot]
    • Filtering  and  Sor:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]List<Pet> filteredDogs = filter(having(on(Pet.class).getSpecies(), is(Dog)), pets);List<Pet> sortedDogs = sort(filteredDogs, on(Pet.class).getName()); [Rover, Spot]
    • Extrac:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]pets.filter(a -> a.getSpecies() == Dog) .map(e -> { return e.getName(); }) .sorted((a, b) -> a.compareTo(b))    .into(new ArrayList<Pet>()); Extracting with Java 8 ["Rover", "Spot"]
    • Extrac:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]List<Pet> dogs = filter(having(on(Pet.class).getSpecies(), is(Dog)), pets);List<String> dogNames = extract(dogs, on(Pet.class).getName());List<String> sortedDogNames = sort(dogNames,on(String.class)); Extracting with LambdaJ ["Rover", "Spot"]
    • Extrac:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]List<Pet> filteredDogs = new ArrayList();for(Pet pet : pets) {    if (pet.getSpecies() == Dog) {        filteredDogs.add(pet);    }}Collections.sort(filteredDogs, new Comparator<Pet>() {    @Override    public int compare(Pet pet, Pet pet1) {        return pet.getName().compareTo(pet1.getName());    }}); Extracting with old-style ["Rover", "Spot"] Java
    • Extrac:ng  in  LambdaJ [Ginger, Spot, Fluffy, Rover]List<Pet> dogs = filter(having(on(Pet.class).getSpecies(), is(Dog)), pets);List<String> dogNames = extract(dogs, on(Pet.class).getName());List<String> sortedDogNames = sort(dogNames,on(String.class)); Extracting with LambdaJ ["Rover", "Spot"]
    • Conver:ng  in  LambdaJList<VetStay> vetStays = pets.map(pet -> { return new VetStay(pet, new Date(), "sore paw");})                             .into(new ArrayList<VetStay>()); Converting with Java 8 convert(pets, toVetStay()); private Converter<Pet, VetStay> toVetStay() {     return new Converter<Pet, VetStay>() {         @Override         public VetStay convert(Pet pet) {             return new VetStay(pet, new Date(), "sore paw");         }     }; } Converting with LambdaJ
    • Grouping  in  LambdaJ [Ginger, Spot, Fluffy, Rover]Group<Pet> petsBySpecies = group(pets,by(on(Pet.class).getSpecies()));List<Pet> dogs = petsBySpecies.find(Dog); [Spot,Rover]
    • FlaOening  in  LambdaJ [[Spot, Rover], [Ginger], [Fluffy]]List<List<Pet>> petsBySpecies = ...List<Pet> allPets = flatten(petsBySpecies); [Spot, Rover, Ginger, Fluffy]
    • Checking  existence  in  LambdaJ [Spot, Rover, Ginger, Fluffy]exists(pets, having(on(Pet.class).getSpecies(), is(Cat))) true
    • Using  Predicates  in  LambdaJPredicate<Pet> carnivores = (pet) -> (pet.getSpecies() == Dog || pet.getSpecies() == Cat);List<Pet> carnivorousPets = pets.filter(carnivores).into(new ArrayList<Pet>()); Java 8Matcher<Pet> carnivore = new Predicate<Pet>() {    public boolean apply(Pet pet) {        return (pet.getSpecies() == Dog || pet.getSpecies() == Cat);    }};List<Pet> carnivores = filter(carnivore, pets); LambdaJ
    • Using  Aggregates  in  LambdaJList<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();
    • Some  real-­‐world  examplesTestOutcome  1 SUCCESS TestOutcome  2 SUCCESS TestOutcome  3 TestOutcome  4 FAILURE PENDING TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS
    • Some  real-­‐world  examples TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS TestOutcome  3 TestOutcome  4 FAILURE PENDINGfilter(having(on(TestOutcome.class).getResult(), is(SUCCESS)), outcomes); TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS
    • Some  real-­‐world  examples TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS TestOutcome  3 TestOutcome  4 FAILURE PENDING filter(withResult(SUCCESS)), outcomes);private Matcher<?> withResult(TestResult expectedResult) {    return having(on(TestOutcome.class).getResult(), is(expectedResult));} TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS
    • Some  real-­‐world  examples TestOutcome  1 SUCCESS TestOutcome  2 SUCCESS TestOutcome  3 TestOutcome  4 FAILURE PENDINGfilter(anyOf(withResult(SUCCESS), withResult(PENDING)), outcomes); TestOutcome  1 SUCCESSTestOutcome  2 SUCCESSTestOutcome  4 PENDING
    • Some  real-­‐world  examplesTestOutcome  1 SUCCESS TestOutcome  2 SUCCESS TestOutcome  3 TestOutcome  4 FAILURE PENDING TestOutcome  2 Step  1 Step  2 Step  3 Step  4
    • Some  real-­‐world  examples Tag Tag 1 TagProvider1 Tag TagProvider2 Tag Tag Tag Tagflatten(extract(TagProviders, on(TagProvider.class).getTags())); Tag Tag 1 Tag Tag Tag Tag Tag
    • And  performance  in  all  that?
    • Keeping  things  maintainable“Excessive use of Guavas functional programming idioms canlead to verbose, confusing, unreadable, and inefficient code.” - the Guava team Can also be true of LambdaJ
    • Keeping  things  maintainable RULE 1Use a functional style when it makes the intent more readable
    • Keeping  things  maintainablesort(extract(filter(having(on(Pet.class).getSpecies(), is(Dog)), pets), on(Pet.class).getName()), on(String.class));List<Pet> dogs = filter(having(on(Pet.class).getSpecies(), is(Dog)), pets);List<String> dogNames = extract(dogs, on(Pet.class).getName());List<String> sortedDogNames = sort(dogNames, on(String.class));
    • Keeping  things  maintainable RULE 2 One-liners are not always better
    • Keeping  things  maintainableconvert(pets,        new Converter<Pet, VetStay>() {                    @Override                    public VetStay convert(Pet pet) {                        return new VetStay(pet, new Date(), "sore paw");                    }        });convert(pets, toVetStay());private Converter<Pet, VetStay> toVetStay() {    return new Converter<Pet, VetStay>() {        @Override        public VetStay convert(Pet pet) {            return new VetStay(pet, new Date(), "sore paw");        }    };}
    • Keeping  things  maintainable RULE 3Write your own domain-specific matchers
    • Keeping  things  maintainableprivate Matcher<?> withResult(TestResult expectedResult) {    return having(on(TestOutcome.class).getResult(), is(expectedResult));} filter(withResult(SUCCESS)), outcomes); select(not(withResult(SUCCESS))), outcomes); select(anyOf(withResult(SKIPPED), withResult(IGNORED)), outcomes);
    • Thank You John  Ferguson  Smartjohn.smart@wakaleo.com  h2p://www.wakaleo.com Twi2er:  wakaleo