📜 ⬆️ ⬇️

Java 8 Lambda vs LambdaJ vs Guava vs Iterative approach

In the middle of 2013, Java 8 comes out with a lambda expression implementation. Lambda expressions provide ample opportunities for application of functional programming style. True, the functional style can be used today in JDK 7, 6 or 5 using the LambdaJ and Guava libraries.
IterativeLambdajJDK 8 lambdaGuava
Print all brands79472 *11379
Select all sales of a Ferrari251464431
Find buys of youngest person1,2091,7751,2421.218
Find the most costly saleeight1235572
Sum costs where both are males23973 *4045
Age of youngest who bought for> 50,0001,5212.576 *1,5601.511
Sort sales by cost3501,187473453
Extract cars original cost29613131
Index cars by brand577089415
Group sales by buyers and sellers2,5863.748 *2,8621.601
Find most bought car7441.023 *CRASH1,435

Guava is a fairly extensive library, but its core is made up of classes for working with collections, the library itself has grown out of google-collections. These classes implement everything for working with collections, which is missing in the JDK today. If you take a closer look at JDK 8, you always get the feeling that this or that new feature already exists in guava. It is possible that the developers of the eighth java relied precisely on the experience of the guava.

LamdaJ, despite its name, does not provide the ability to write lambda expressions, it is rather a library for working with collections. It gives you the ability to filter, convert, group items of collections, while the code is very compact and readable. It is implemented by means of reflection and glib, and it is obvious that one has to pay for productivity with productivity. About LambdaJ already wrote on Habré .

In JDK 8, lambda expressions will be implemented already at the compiler level and will be converted to bytecode at the compilation stage, therefore, theoretically, the performance of such code should be higher.
')

Performance comparison


In order to practically compare the performance of lambda expressions from JDK 8 with LambdaJ, Guava and the usual iterative approach, LambdaJ performance tests were taken and analogs were written on JDK 8 and Guava.

The initial test code for the iterative variant and LambdaJ was not touched, the test names are saved in English to avoid confusion. The testing methodology is as follows: tests are run in 100 passes, where each test is run 100,000 times, the total time taken to complete each pass is measured and averaged.

Not all LambdaJ tests were launched in JRE 8, they are marked with an asterisk in the table, the results for them were measured in JRE 7. In one test, the lambda expression dropped the virtual machine completely.

The tests were performed on a computer with the following configuration: Core i5 760 2.8 GHz 8 GB Win 7 sp-1 64 bit lambda-8-b45-windows-x64-24_jun_2012 jdk-7u4-windows-x64.

As a result, the best results were given by the iterative code, Guava and JDK lambda. They give quite comparable results. In general, we can say that lambda expressions provide a completely satisfactory replacement for iterations and anonymous classes. Both JDK 8, Guava, and the iterative approach give very similar results, but LamdaJ is almost an order of magnitude behind, the reason most likely lies in the wide use of reflection.

It should be noted that Guava and JDK lambda have one feature when working with collections. They often return not the copied collection, but its live view, which postpones the calculations until the time it accesses the elements of this view. Therefore, in the tests, all the live views were clearly converted into collections. Otherwise, some tests would give a result of almost 0 milliseconds. I also have to say that in real life no one demands to make a choice in favor of any approach, for example, Guava will be perfectly combined with lambda expressions.

Example


For an example of how the source code for each of the approaches looks like, you can look at the FindAgeOfYoungestWhoBoughtForMoreThan50000Test test. In this test, a list of car dealership sales is given, and in this list is the age of the youngest buyer who made the purchase for more than 50,000 any money.

Iterative approach

int age = Integer.MAX_VALUE; for (final Sale sale : db.getSales()) { if (sale.getCost() > 50000.00) { final int buyerAge = sale.getBuyer().getAge(); if (buyerAge < age) { age = buyerAge; } } } 

LambdaJ

 final int age = Lambda.min(forEach(select(db.getSales(), having(on(Sale.class).getCost(), greaterThan(50000.00)))).getBuyer(), on(Person.class).getAge()); 

JDK 8 lambda

 final int age = Collections.min(db.getSales() .filter((Sale sale)->sale.getCost() > 50000.00) .<Integer>map((Sale sale)->sale.getBuyer().getAge()) .into(new ArrayList<Integer>())); 

Guava

 final int age = Collections.min(transform(filter(db.getSales(), new Predicate<Sale>() { @Override public boolean apply(final Sale input) { return input.getCost() > 50000.00; } }), new Function<Sale, Integer>() { @Override public Integer apply(final Sale input) { return input.getBuyer().getAge(); } })); 


Links




Update


On the advice of TheShade, I made changes to the testing procedure: I added warming up and calculation of confidence intervals. Results changed as follows:
IterativeLambdajJDK 8 lambdaGuava
Print all brands797.34,436.6 *1,073.2912.1
Select all sales of a Ferrari471.11,359.6398.5341.7
Find buys of youngest person12,102.417.436.212,267.412,144.5
Find the most costly sale89.71,237.2742.8676.6
Sum costs where both are males173.78,979.8 *372.7394.5
Age of youngest who bought for> 50,00011,971.228,091.9 *11,672.115,975.6
Sort sales by cost3.26112,566.14,558.83,242.5
Extract cars original cost292.1628322.8213.1
Index cars by brand548.8672.1867.84,324.6
Group sales by buyers and sellers25,986.339,339.3 *28,109.215,068.9
Find most bought car7,378.39,317.2 *CRASH10,002.1

Source: https://habr.com/ru/post/146718/


All Articles