SlideShare ist ein Scribd-Unternehmen logo
1 von 31
Downloaden Sie, um offline zu lesen
No more loops with

            λambdaj
An internal DSL to manipulate
  collections without loops

     by Mario Fusco
 mario.fusco@gmail.com
  twitter: @mariofusco
Why is lambdaj born?
The best way to understand what lambdaj
does and how it works is to start asking
why we felt the need to develop it:

  We were on a project with a complex data model
                                                     j
  The biggest part of our business logic did almost
  always the same: iterating over collections of our
  business objects in order to do the same set of tasks
  Loops (especially when nested or mixed with
  conditions) are harder to be read than to be written
  We wanted to write our business logic in a less
  technical and closer to business fashion
What is lambdaj for?
 It provides a DSL to manipulate collections in a
 pseudo-functional and statically typed way.
 It eliminates the burden to write (often poorly
 readable) loops while iterating over collections.
                                                     j
 It allows to iterate collections in order to:


convert
                         aggregate
 filter          index

                      group
          sort                   extract
How does lambdaj work?
lambdaj is a thread safe library of static
methods based on 2 main features:

  treating a collection as it was a single object by
  allowing to propagate a single method invocation
                                                       j
  to all the objects in the collection

forEach(personsInFamily).setLastName("Fusco");

  allowing to define a reference to a java method in
  a statically typed way

sort(persons, on(Person.class).getAge());
The Demo Data Model
Print all cars’ brands
  Iterative version:

StringBuilder sb = new StringBuilder();
                                                             j
for (Car car : cars)
   sb.append(car.getBrand()).append(", ");
String brands = sb.toString().substring(0, sb.length()-2);


  lambdaj version:

String brands = joinFrom(cars).getBrand();
Select all sales of a Ferrari
  Iterative version:

List<Sale> salesOfAFerrari = new ArrayList<Sale>();
for (Sale sale : sales) {
   if (sale.getCar().getBrand().equals("Ferrari"))
                                                             j
        salesOfAFerrari.add(sale);
}



  lambdaj version:

List<Sale> salesOfAFerrari = select(sales,
  having(on(Sale.class).getCar().getBrand(),equalTo("Ferrari")));
Find buys of youngest person

  Iterative version:
Person youngest = null;
for (Person person : persons)
                                                              j
   if (youngest == null || person.getAge() < youngest.getAge())
        youngest = person;
List<Sale> buys = new ArrayList<Sale>();
for (Sale sale : sales)
   if (sale.getBuyer().equals(youngest)) buys.add(sale);


  lambdaj version:
List<Sale> sales = select(sales,having(on(Sale.class).getBuyer(),
   equalTo(selectMin(persons, on(Person.class).getAge()))));
Find most costly sale
    Iterative version:

double maxCost = 0.0;
                                                             j
for (Sale sale : sales) {
     double cost = sale.getCost();
     if (cost > maxCost) maxCost = cost;
}


    lambdaj version:

Sol. 1 -> double maxCost = max(sales, on(Sale.class).getCost());
Sol. 2 -> double maxCost = maxFrom(sales).getCost();
Sum costs where both are males
  Iterative version:

double sum = 0.0;
for (Sale sale : sales) {
                                                                j
   if (sale.getBuyer().isMale() && sale.getSeller().isMale())
        sum += sale.getCost();
}


  lambdaj version:

double sum = sumFrom(select(sales,
   having(on(Sale.class).getBuyer().isMale()).and(
   having(on(Sale.class).getSeller().isMale())))).getCost();
Find age of youngest who
bought for more than 50,000
  Iterative version:
int age = Integer.MAX_VALUE;
                                                               j
for (Sale sale : sales) {
   if (sale.getCost() > 50000.00) {
        int buyerAge = sale.getBuyer().getAge();
        if (buyerAge < age) age = buyerAge;
   }
}
  lambdaj version:
int age = min(forEach(select(sales,
   having(on(Sale.class).getCost(), greaterThan(50000.00))))
   .getBuyer(), on(Person.class).getAge());
Sort sales by cost
  Iterative version:

List<Sale> sortedSales = new ArrayList<Sale>(sales);
Collections.sort(sortedSales, new Comparator<Sale>() {
                                                              j
   public int compare(Sale s1, Sale s2) {
      return Double.valueOf(s1.getCost()).compareTo(s2.getCost());
   }
});


  lambdaj version:

List<Sale> sortedSales = sort(sales, on(Sale.class).getCost());
Extract cars’ original cost
  Iterative version:

List<Double> costs = new ArrayList<Double>();
for (Car car : cars)
                                                          j
    costs.add(car.getOriginalValue());


  lambdaj version:

List<Double> costs =
       extract(cars, on(Car.class).getOriginalValue());
Index cars by brand
  Iterative version:

Map<String, Car> carsByBrand = new HashMap<String, Car>();
for (Car car : cars)
                                                             j
    carsByBrand.put(car.getBrand(), car);


  lambdaj version:

Map<String, Car> carsByBrand =
       index(cars, on(Car.class).getBrand());
Group sales by buyers and sellers
                    (iterative version)

   Person buyer = sale.getBuyer();
   Map<Person, Sale> buyerMap = map.get(buyer);
   if (buyerMap == null) {
        buyerMap = new HashMap<Person, Sale>();
                                                                     j
Map<Person,Map<Person,Sale>> map = new HashMap<Person,Map<Person,Sale>>();
for (Sale sale : sales) {




        map.put(buyer, buyerMap);
   }
   buyerMap.put(sale.getSeller(), sale);
}
Person youngest = null;
Person oldest = null;
for (Person person : persons) {
   if (youngest == null || person.getAge() < youngest.getAge())
        youngest = person;
   if (oldest == null || person.getAge() > oldest.getAge())
        oldest = person;
}
Sale saleFromYoungestToOldest = map.get(youngest).get(oldest);
Group sales by buyers and sellers
                  (lambdaj version)
Group<Sale> group = group(sales,                              j
   by(on(Sale.class).getBuyer()),by(on(Sale.class).getSeller()));
Person youngest = selectMin(persons, on(Person.class).getAge());
Person oldest = selectMax(persons, on(Person.class).getAge());
Sale sale = group.findGroup(youngest).findGroup(oldest).first();
Find most bought car
       (iterative version)
Map<Car, Integer> carsBought = new HashMap<Car, Integer>();
for (Sale sale : sales) {
   Car car = sale.getCar();
   Integer boughtTimes = carsBought.get(car);
                                                              j
   carsBought.put(car, boughtTimes == null ? 1 : boughtTimes+1);
}

Car mostBoughtCarIterative = null;
int boughtTimesIterative = 0;
for (Entry<Car, Integer> entry : carsBought.entrySet()) {
   if (entry.getValue() > boughtTimesIterative) {
        mostBoughtCarIterative = entry.getKey();
        boughtTimesIterative = entry.getValue();
   }
}
Find most bought car
       (lambdaj version)
Group<Sale> group = selectMax(
   group(sales, by(on(Sale.class).getCar())).subgroups(),
   on(Group.class).getSize());
Car mostBoughtCar = group.first().getCar();
                                                            j
int boughtTimes = group.getSize();
How does lambdaj work?
 The getCar() invocation is propagated by the first proxy to all the
 sales. The cars returned by these invocations are put again in a
 list and another proxy, similar to the first one, is created to wrap
 this list, allowing to repeat this type of invocation once more
 (proxy concatenation).
                                                                      j
            Car fastestCar = max(

                    forEach(sales).getCar(),

A proxy wraps the          on(Car.class).getSpeed());
list of sales. The
returned object is of
class Sale but             A proxy of the Car class is created in
dynamically                order to register the invocations on it.
implements the             These invocations will be then
Iterable interface too     reapplied to the cars of the former list
Lambdaj’s extensibility
List<Double> speeds = extract(cars, on(Car.class).getSpeed());


                      is the short form for:
                                                               j
List<Double> speeds = convert(cars, new Car2SpeedConverter());


          where the Car2SpeedConverter is defined as:

class Car2SpeedConverter implements Converter<Car, Double> {
    public Double convert(Car car) {
        return car.getSpeed();
    }
}
Performance analysis
Minimum, maximum and average duration in
milliseconds of 20 runs with 100,000 iterations of the
former examples
                                           iterative                    lambdaj
                                   min        max      avg      min       max      avg       ratio
PrintAllBrands                       265        312      283    1,310     1,591    1,377    4.866
FindAllSalesOfAFerrari               281        437      366    1,528     1,607    1,566    4.279
FindAllBuysOfYoungestPerson        5,585      5,975    5,938    6,895     6,989    6,936    1.168
FindMostCostlySaleValue              218        234      227      655       702      670    2.952
SumCostsWhereBothActorsAreAMale      358        452      375    2,199     2,637    2,247    5.992
AgeOfYoungestBuyerForMoreThan50K   5,257      5,319    5,292    9,625     9,750    9,696    1.832
SortSalesByCost                    1,388      1,482    1,448    3,213     3,245    3,231    2.231
ExtractCarsOriginalCost              140        156      141      234       249      236    1.674
IndexCarsByBrand                     172        203      186      327       343      336    1.806
GroupSalesByBuyersAndSellers       9,469      9,766    9,507   12,698    12,838   12,753    1.341
FindMostBoughtCar                  3,744      3,884    3,846    4,181     4,259     4211    1.095


                                                                   Average ratio =         2.658
Known limitations
  Lack of reified generics     lambdaj cannot
  infer the actual type to be returned when a
  null or empty collection is passed to forEach()

List<Person> persons = new ArrayList<Person>();
                                                              j
forEach(persons).setLastName("Fusco");
      Exception

  Impossibility to proxy a final class
  the on() construct cannot register an
  invocation after a final Class is met

List<Person> sortedByNamePersons =
   sort(persons, on(Person.class).getName().toLowerCase());
      Exception
Let’s write it fluently

Fluent                    j
 Interface
  Collections
Why Fluent Interfaces
List<Person> richBuyersSortedByAge =
    sort(
        extract(
            select(sales,
                 having(on(Sale.class).getValue(),
                 greaterThan(50000)))
                                                             j
       ), on(Sale.class).getBuyer()
    ), on(Person.class).getAge());



List<Person> richBuyersSortedByAge = with(sales)
    .retain(having(on(Sale.class).getValue(),greaterThan(50000)))
    .extract(on(Sale.class).getBuyer())
    .sort(on(Person.class).getAge());
LambdaCollections
 LambdaCollections implement the                  java.util.List
 corresponding Java interface (i.e.        add()
                                                          implements
 LambdaList is a java.util.List) so you
 can use them in all other API
                                                      LambdaList
 They enrich the Java Collection          add()

 Framework API with a fluent
 interface that allows to use the                  java.util.List
 lambdaj's features
                                                   aggregate()
 Invoking the methods of this fluent      sort()                   retain()
 interface also change the state of         group()
                                                       convert()
                                                                   clone()
 the original wrapped collection
 The instance of the wrapped collection doesn’t change so its
 characteristics are always reflected even by the wrapping
 lambdaj counterpart
 If you need to leave the original collection unchanged clone it:
      with(sales).clone().remove(…) …
Let’s go functional


    Closures
                            j
(actually lambda expressions)
lambdaj's closure
Closures (or more properly lambda expressions) can
be defined through the usual lambdaj DSL style
   Closure println = closure(); {
      of(System.out).println(var(String.class));
                                                    j
   }


and then invoked by "closing" its free variable once:
   println.apply("one");


or more times:
   println.each("one", "two", "three");
Closure’s features
   Typed closure
                                                                     j
Closure2<Integer,Integer> adder = closure(Integer.class, Integer.class); {

}
   of(this).sum(var(Integer.class), var(Integer.class));



   Curry
Closure1<Integer> adderOf10 = adder.curry2(10);


   Mix variables and fixed values
Closure1<Integer> adderOf10 = closure(Integer.class); {
   of(this).sum(var(Integer.class), 10);
}


   Cast a closure to a one-method interface (SAM)
Converter<Integer,Integer> converter = adderOf10.cast(Converter.class);
Closure’s features (2)
   Keep unbound the object on which the closure is invoked


   }
       of(Person.class).setAge(var(Integer.class));

   Define a closure without using a ThreadLocal
                                                                      j
Closure2<Person, Integer> ageSetter = closure(Person.class, Integer.class); {




Closure2<Person, Integer> ageSetter = new Closure2<Person, Integer>() {{
       of(Person.class).setAge(var(Integer.class));
   }};
   Define the invocation of a static method …
Closure1<String> intParser = closure(String.class)
        .of(Integer.class, "parseInt", var(String.class));
   … or of a constructor
Closure2<String, Integer> personCreator = closure()
       .of(Person.class, CONSTRUCTOR, var(String.class), var(Integer.class));
Switcher
public List<String> sortStrings(List<String> list) {

}
       // a sort algorithm suitable for Strings

public List<T> sortSmallList(List<T> list) {

}
       // a sort algorithm suitable for no more than 100 items
                                                                        j
public List<String> sort(List<String> list) {
       // a generic sort algorithm
}



Switcher<List<T>> sortStrategy = new Switcher<List<T>>()
   .addCase(having(on(List.class).get(0), instanceOf(String.class))),
        new Closure() {{ of(this).sortStrings(var(List.class)); }})
   .addCase(having(on(List.class).size(), lessThan(100))),
        new Closure() {{ of(this).sortSmallList(var(List.class)); }})
   .setDefault(new Closure() {{ of(this).sort(var(List.class)); }});
Check out lambdaj at:
http://lambdaj.googlecode.com

             Thank you

Mario Fusco
mario.fusco@gmail.com
twitter: @mariofusco

Weitere ähnliche Inhalte

Was ist angesagt?

Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Philip Schwarz
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Type Classes in Scala and Haskell
Type Classes in Scala and HaskellType Classes in Scala and Haskell
Type Classes in Scala and HaskellHermann Hueck
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondMario Fusco
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerMario Fusco
 
Introduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScriptIntroduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScripttmont
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
Jumping-with-java8
Jumping-with-java8Jumping-with-java8
Jumping-with-java8Dhaval Dalal
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardKelsey Gilmore-Innis
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioLuis Atencio
 
Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)RichardWarburton
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMMario Fusco
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional ProgrammingHugo Firth
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
Introduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in HaskellIntroduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in Haskellnebuta
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)stasimus
 

Was ist angesagt? (20)

Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Type Classes in Scala and Haskell
Type Classes in Scala and HaskellType Classes in Scala and Haskell
Type Classes in Scala and Haskell
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better Programmer
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Introduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScriptIntroduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScript
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Jumping-with-java8
Jumping-with-java8Jumping-with-java8
Jumping-with-java8
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a Neckbeard
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis Atencio
 
DIWE - Advanced PHP Concepts
DIWE - Advanced PHP ConceptsDIWE - Advanced PHP Concepts
DIWE - Advanced PHP Concepts
 
Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional Programming
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Introduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in HaskellIntroduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in Haskell
 
Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)Introduction to Monads in Scala (1)
Introduction to Monads in Scala (1)
 

Ähnlich wie No more loops with lambdaj

PorfolioReport
PorfolioReportPorfolioReport
PorfolioReportAlbert Chu
 
Streams and lambdas the good, the bad and the ugly
Streams and lambdas the good, the bad and the uglyStreams and lambdas the good, the bad and the ugly
Streams and lambdas the good, the bad and the uglyPeter Lawrey
 
JDD2014: Real life lambdas - Peter Lawrey
JDD2014: Real life lambdas - Peter LawreyJDD2014: Real life lambdas - Peter Lawrey
JDD2014: Real life lambdas - Peter LawreyPROIDEA
 
MongoDB World 2018: Keynote
MongoDB World 2018: KeynoteMongoDB World 2018: Keynote
MongoDB World 2018: KeynoteMongoDB
 
w3schools.com THE WORLDS LARGEST WEB DEVELOPER SITE
w3schools.com  THE WORLDS LARGEST WEB DEVELOPER SITE w3schools.com  THE WORLDS LARGEST WEB DEVELOPER SITE
w3schools.com THE WORLDS LARGEST WEB DEVELOPER SITE tidwellerin392
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDebasish Ghosh
 
Below is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfBelow is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfarmanuelraj
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaHermann Hueck
 
Practical scalaz
Practical scalazPractical scalaz
Practical scalazoxbow_lakes
 
Creating an Uber Clone - Part XXVII - Transcript.pdf
Creating an Uber Clone - Part XXVII - Transcript.pdfCreating an Uber Clone - Part XXVII - Transcript.pdf
Creating an Uber Clone - Part XXVII - Transcript.pdfShaiAlmog1
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in JavascriptKnoldus Inc.
 
Functional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesFunctional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesAndrás Papp
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstractionIntro C# Book
 
Legacy lambda code
Legacy lambda codeLegacy lambda code
Legacy lambda codePeter Lawrey
 
Django 1.1 Tour
Django 1.1 TourDjango 1.1 Tour
Django 1.1 TourIdan Gazit
 
12. Basic SQL Queries (2).pptx
12. Basic SQL Queries  (2).pptx12. Basic SQL Queries  (2).pptx
12. Basic SQL Queries (2).pptxSabrinaShanta2
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererRuby Meditation
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 

Ähnlich wie No more loops with lambdaj (20)

PorfolioReport
PorfolioReportPorfolioReport
PorfolioReport
 
Streams and lambdas the good, the bad and the ugly
Streams and lambdas the good, the bad and the uglyStreams and lambdas the good, the bad and the ugly
Streams and lambdas the good, the bad and the ugly
 
JDD2014: Real life lambdas - Peter Lawrey
JDD2014: Real life lambdas - Peter LawreyJDD2014: Real life lambdas - Peter Lawrey
JDD2014: Real life lambdas - Peter Lawrey
 
MongoDB World 2018: Keynote
MongoDB World 2018: KeynoteMongoDB World 2018: Keynote
MongoDB World 2018: Keynote
 
w3schools.com THE WORLDS LARGEST WEB DEVELOPER SITE
w3schools.com  THE WORLDS LARGEST WEB DEVELOPER SITE w3schools.com  THE WORLDS LARGEST WEB DEVELOPER SITE
w3schools.com THE WORLDS LARGEST WEB DEVELOPER SITE
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
 
Below is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfBelow is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdf
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from Scala
 
Practical scalaz
Practical scalazPractical scalaz
Practical scalaz
 
Creating an Uber Clone - Part XXVII - Transcript.pdf
Creating an Uber Clone - Part XXVII - Transcript.pdfCreating an Uber Clone - Part XXVII - Transcript.pdf
Creating an Uber Clone - Part XXVII - Transcript.pdf
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in Javascript
 
Functional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesFunctional programming techniques in real-world microservices
Functional programming techniques in real-world microservices
 
XKE Typeclass
XKE TypeclassXKE Typeclass
XKE Typeclass
 
Joy of scala
Joy of scalaJoy of scala
Joy of scala
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstraction
 
Legacy lambda code
Legacy lambda codeLegacy lambda code
Legacy lambda code
 
Django 1.1 Tour
Django 1.1 TourDjango 1.1 Tour
Django 1.1 Tour
 
12. Basic SQL Queries (2).pptx
12. Basic SQL Queries  (2).pptx12. Basic SQL Queries  (2).pptx
12. Basic SQL Queries (2).pptx
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 

Mehr von Mario Fusco

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automationMario Fusco
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...Mario Fusco
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep diveMario Fusco
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Mario Fusco
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVMMario Fusco
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingMario Fusco
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageMario Fusco
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing DroolsMario Fusco
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife SpringMario Fusco
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 

Mehr von Mario Fusco (13)

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...
 
OOP and FP
OOP and FPOOP and FP
OOP and FP
 
Lazy java
Lazy javaLazy java
Lazy java
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep dive
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVM
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional Programming
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same language
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing Drools
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 

Kürzlich hochgeladen

Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 

Kürzlich hochgeladen (20)

Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 

No more loops with lambdaj

  • 1. No more loops with λambdaj An internal DSL to manipulate collections without loops by Mario Fusco mario.fusco@gmail.com twitter: @mariofusco
  • 2. Why is lambdaj born? The best way to understand what lambdaj does and how it works is to start asking why we felt the need to develop it: We were on a project with a complex data model j The biggest part of our business logic did almost always the same: iterating over collections of our business objects in order to do the same set of tasks Loops (especially when nested or mixed with conditions) are harder to be read than to be written We wanted to write our business logic in a less technical and closer to business fashion
  • 3. What is lambdaj for? It provides a DSL to manipulate collections in a pseudo-functional and statically typed way. It eliminates the burden to write (often poorly readable) loops while iterating over collections. j It allows to iterate collections in order to: convert aggregate filter index group sort extract
  • 4. How does lambdaj work? lambdaj is a thread safe library of static methods based on 2 main features: treating a collection as it was a single object by allowing to propagate a single method invocation j to all the objects in the collection forEach(personsInFamily).setLastName("Fusco"); allowing to define a reference to a java method in a statically typed way sort(persons, on(Person.class).getAge());
  • 6. Print all cars’ brands Iterative version: StringBuilder sb = new StringBuilder(); j for (Car car : cars) sb.append(car.getBrand()).append(", "); String brands = sb.toString().substring(0, sb.length()-2); lambdaj version: String brands = joinFrom(cars).getBrand();
  • 7. Select all sales of a Ferrari Iterative version: List<Sale> salesOfAFerrari = new ArrayList<Sale>(); for (Sale sale : sales) { if (sale.getCar().getBrand().equals("Ferrari")) j salesOfAFerrari.add(sale); } lambdaj version: List<Sale> salesOfAFerrari = select(sales, having(on(Sale.class).getCar().getBrand(),equalTo("Ferrari")));
  • 8. Find buys of youngest person Iterative version: Person youngest = null; for (Person person : persons) j if (youngest == null || person.getAge() < youngest.getAge()) youngest = person; List<Sale> buys = new ArrayList<Sale>(); for (Sale sale : sales) if (sale.getBuyer().equals(youngest)) buys.add(sale); lambdaj version: List<Sale> sales = select(sales,having(on(Sale.class).getBuyer(), equalTo(selectMin(persons, on(Person.class).getAge()))));
  • 9. Find most costly sale Iterative version: double maxCost = 0.0; j for (Sale sale : sales) { double cost = sale.getCost(); if (cost > maxCost) maxCost = cost; } lambdaj version: Sol. 1 -> double maxCost = max(sales, on(Sale.class).getCost()); Sol. 2 -> double maxCost = maxFrom(sales).getCost();
  • 10. Sum costs where both are males Iterative version: double sum = 0.0; for (Sale sale : sales) { j if (sale.getBuyer().isMale() && sale.getSeller().isMale()) sum += sale.getCost(); } lambdaj version: double sum = sumFrom(select(sales, having(on(Sale.class).getBuyer().isMale()).and( having(on(Sale.class).getSeller().isMale())))).getCost();
  • 11. Find age of youngest who bought for more than 50,000 Iterative version: int age = Integer.MAX_VALUE; j for (Sale sale : sales) { if (sale.getCost() > 50000.00) { int buyerAge = sale.getBuyer().getAge(); if (buyerAge < age) age = buyerAge; } } lambdaj version: int age = min(forEach(select(sales, having(on(Sale.class).getCost(), greaterThan(50000.00)))) .getBuyer(), on(Person.class).getAge());
  • 12. Sort sales by cost Iterative version: List<Sale> sortedSales = new ArrayList<Sale>(sales); Collections.sort(sortedSales, new Comparator<Sale>() { j public int compare(Sale s1, Sale s2) { return Double.valueOf(s1.getCost()).compareTo(s2.getCost()); } }); lambdaj version: List<Sale> sortedSales = sort(sales, on(Sale.class).getCost());
  • 13. Extract cars’ original cost Iterative version: List<Double> costs = new ArrayList<Double>(); for (Car car : cars) j costs.add(car.getOriginalValue()); lambdaj version: List<Double> costs = extract(cars, on(Car.class).getOriginalValue());
  • 14. Index cars by brand Iterative version: Map<String, Car> carsByBrand = new HashMap<String, Car>(); for (Car car : cars) j carsByBrand.put(car.getBrand(), car); lambdaj version: Map<String, Car> carsByBrand = index(cars, on(Car.class).getBrand());
  • 15. Group sales by buyers and sellers (iterative version) Person buyer = sale.getBuyer(); Map<Person, Sale> buyerMap = map.get(buyer); if (buyerMap == null) { buyerMap = new HashMap<Person, Sale>(); j Map<Person,Map<Person,Sale>> map = new HashMap<Person,Map<Person,Sale>>(); for (Sale sale : sales) { map.put(buyer, buyerMap); } buyerMap.put(sale.getSeller(), sale); } Person youngest = null; Person oldest = null; for (Person person : persons) { if (youngest == null || person.getAge() < youngest.getAge()) youngest = person; if (oldest == null || person.getAge() > oldest.getAge()) oldest = person; } Sale saleFromYoungestToOldest = map.get(youngest).get(oldest);
  • 16. Group sales by buyers and sellers (lambdaj version) Group<Sale> group = group(sales, j by(on(Sale.class).getBuyer()),by(on(Sale.class).getSeller())); Person youngest = selectMin(persons, on(Person.class).getAge()); Person oldest = selectMax(persons, on(Person.class).getAge()); Sale sale = group.findGroup(youngest).findGroup(oldest).first();
  • 17. Find most bought car (iterative version) Map<Car, Integer> carsBought = new HashMap<Car, Integer>(); for (Sale sale : sales) { Car car = sale.getCar(); Integer boughtTimes = carsBought.get(car); j carsBought.put(car, boughtTimes == null ? 1 : boughtTimes+1); } Car mostBoughtCarIterative = null; int boughtTimesIterative = 0; for (Entry<Car, Integer> entry : carsBought.entrySet()) { if (entry.getValue() > boughtTimesIterative) { mostBoughtCarIterative = entry.getKey(); boughtTimesIterative = entry.getValue(); } }
  • 18. Find most bought car (lambdaj version) Group<Sale> group = selectMax( group(sales, by(on(Sale.class).getCar())).subgroups(), on(Group.class).getSize()); Car mostBoughtCar = group.first().getCar(); j int boughtTimes = group.getSize();
  • 19. How does lambdaj work? The getCar() invocation is propagated by the first proxy to all the sales. The cars returned by these invocations are put again in a list and another proxy, similar to the first one, is created to wrap this list, allowing to repeat this type of invocation once more (proxy concatenation). j Car fastestCar = max( forEach(sales).getCar(), A proxy wraps the on(Car.class).getSpeed()); list of sales. The returned object is of class Sale but A proxy of the Car class is created in dynamically order to register the invocations on it. implements the These invocations will be then Iterable interface too reapplied to the cars of the former list
  • 20. Lambdaj’s extensibility List<Double> speeds = extract(cars, on(Car.class).getSpeed()); is the short form for: j List<Double> speeds = convert(cars, new Car2SpeedConverter()); where the Car2SpeedConverter is defined as: class Car2SpeedConverter implements Converter<Car, Double> { public Double convert(Car car) { return car.getSpeed(); } }
  • 21. Performance analysis Minimum, maximum and average duration in milliseconds of 20 runs with 100,000 iterations of the former examples iterative lambdaj min max avg min max avg ratio PrintAllBrands 265 312 283 1,310 1,591 1,377 4.866 FindAllSalesOfAFerrari 281 437 366 1,528 1,607 1,566 4.279 FindAllBuysOfYoungestPerson 5,585 5,975 5,938 6,895 6,989 6,936 1.168 FindMostCostlySaleValue 218 234 227 655 702 670 2.952 SumCostsWhereBothActorsAreAMale 358 452 375 2,199 2,637 2,247 5.992 AgeOfYoungestBuyerForMoreThan50K 5,257 5,319 5,292 9,625 9,750 9,696 1.832 SortSalesByCost 1,388 1,482 1,448 3,213 3,245 3,231 2.231 ExtractCarsOriginalCost 140 156 141 234 249 236 1.674 IndexCarsByBrand 172 203 186 327 343 336 1.806 GroupSalesByBuyersAndSellers 9,469 9,766 9,507 12,698 12,838 12,753 1.341 FindMostBoughtCar 3,744 3,884 3,846 4,181 4,259 4211 1.095 Average ratio = 2.658
  • 22. Known limitations Lack of reified generics lambdaj cannot infer the actual type to be returned when a null or empty collection is passed to forEach() List<Person> persons = new ArrayList<Person>(); j forEach(persons).setLastName("Fusco"); Exception Impossibility to proxy a final class the on() construct cannot register an invocation after a final Class is met List<Person> sortedByNamePersons = sort(persons, on(Person.class).getName().toLowerCase()); Exception
  • 23. Let’s write it fluently Fluent j Interface Collections
  • 24. Why Fluent Interfaces List<Person> richBuyersSortedByAge = sort( extract( select(sales, having(on(Sale.class).getValue(), greaterThan(50000))) j ), on(Sale.class).getBuyer() ), on(Person.class).getAge()); List<Person> richBuyersSortedByAge = with(sales) .retain(having(on(Sale.class).getValue(),greaterThan(50000))) .extract(on(Sale.class).getBuyer()) .sort(on(Person.class).getAge());
  • 25. LambdaCollections LambdaCollections implement the java.util.List corresponding Java interface (i.e. add() implements LambdaList is a java.util.List) so you can use them in all other API LambdaList They enrich the Java Collection add() Framework API with a fluent interface that allows to use the java.util.List lambdaj's features aggregate() Invoking the methods of this fluent sort() retain() interface also change the state of group() convert() clone() the original wrapped collection The instance of the wrapped collection doesn’t change so its characteristics are always reflected even by the wrapping lambdaj counterpart If you need to leave the original collection unchanged clone it: with(sales).clone().remove(…) …
  • 26. Let’s go functional Closures j (actually lambda expressions)
  • 27. lambdaj's closure Closures (or more properly lambda expressions) can be defined through the usual lambdaj DSL style Closure println = closure(); { of(System.out).println(var(String.class)); j } and then invoked by "closing" its free variable once: println.apply("one"); or more times: println.each("one", "two", "three");
  • 28. Closure’s features Typed closure j Closure2<Integer,Integer> adder = closure(Integer.class, Integer.class); { } of(this).sum(var(Integer.class), var(Integer.class)); Curry Closure1<Integer> adderOf10 = adder.curry2(10); Mix variables and fixed values Closure1<Integer> adderOf10 = closure(Integer.class); { of(this).sum(var(Integer.class), 10); } Cast a closure to a one-method interface (SAM) Converter<Integer,Integer> converter = adderOf10.cast(Converter.class);
  • 29. Closure’s features (2) Keep unbound the object on which the closure is invoked } of(Person.class).setAge(var(Integer.class)); Define a closure without using a ThreadLocal j Closure2<Person, Integer> ageSetter = closure(Person.class, Integer.class); { Closure2<Person, Integer> ageSetter = new Closure2<Person, Integer>() {{ of(Person.class).setAge(var(Integer.class)); }}; Define the invocation of a static method … Closure1<String> intParser = closure(String.class) .of(Integer.class, "parseInt", var(String.class)); … or of a constructor Closure2<String, Integer> personCreator = closure() .of(Person.class, CONSTRUCTOR, var(String.class), var(Integer.class));
  • 30. Switcher public List<String> sortStrings(List<String> list) { } // a sort algorithm suitable for Strings public List<T> sortSmallList(List<T> list) { } // a sort algorithm suitable for no more than 100 items j public List<String> sort(List<String> list) { // a generic sort algorithm } Switcher<List<T>> sortStrategy = new Switcher<List<T>>() .addCase(having(on(List.class).get(0), instanceOf(String.class))), new Closure() {{ of(this).sortStrings(var(List.class)); }}) .addCase(having(on(List.class).size(), lessThan(100))), new Closure() {{ of(this).sortSmallList(var(List.class)); }}) .setDefault(new Closure() {{ of(this).sort(var(List.class)); }});
  • 31. Check out lambdaj at: http://lambdaj.googlecode.com Thank you Mario Fusco mario.fusco@gmail.com twitter: @mariofusco