Monday, 26 May 2014

How to efficiently add BigDecimals

Anyone who deals with monetary values knows that double/float won't cut the mustard and if you deal with prices and FX rates, then BigDecimal is the only real option.

This comes with a lot of potential issues, BigDecimal methods do not handle null very well (i.e. not at all) and sometimes a bug crops up because BigDecimal returns new instances.


So the ObjectLabKit Util package will help, but here is a question for you... what is an efficient way to sum a list of BigDecimal coming from a Class.

Assume that we have a list of 500 Test instances and that we need to sum the Test.value and that value could be null.

We shall run the test 1,000 times.


Option 1: Use Total in a for loop

Option 2: Use Total with java8 forEach

Option 3: Use Total and java8 map()

Option 4: Use Java8 map and reduce

Option 5: Use Java8 map, reduce and accumulator

Option 6: Use Java8 and home-made Collector

Option 7: Use Java8 and ObjectLabKit Calculator

Option 8: Use Java8 and Parallel Stream



So what are the results?

On my 2012 MacBook Pro for a list of 500 Test instances.
AlgoAverage (ms)Min (ms)Max (ms)
Use Total in a for loop0.104
Use Total with java8 forEach0.1040
Use Total and java8 map()0.106
Use Java8 map and reduce002
Use Java8 map, reduce and accumulator002
Use Java8 and home-made Collector0.106
Use Java8 and ObjectLabKit Calculator002
Use Java8 and Parallel Stream0.1010


First of all, the value generated is the same for every algo, so no bug there it seems.

The results are quite similar except for the Max value, implying a greater deviation in the results. I've used JAmon for measuring min/max and average time.

Surprisingly, it seems that forEach has at least 1 execution at 40ms, which is way above the rest. Otherwise using the ObjectLabKit Calculator seems a good compromise between having to write the reduce correctly (! watch out if the BigDecimal on the right is null!) and using the raw map/reduce. 

The Parallel Stream is not as efficient, as it takes some time to coordinate the tasks and split the list. let's see if it gets any different with more data. 

On my 2012 MacBook Pro (QuadCore) for a list of 50,000 Test instances and the parallelStream is then becoming the most efficient.

AlgoAverage (ms)Min (ms)Max (ms)
Use Total in a for loop1020
Use Total with java8 forEach1.1048
Use Total and java8 map()2.1140
Use Java8 map and reduce1.219
Use Java8 map, reduce and accumulator1.2110
Use Java8 and home-made Collector1.4112
Use Java8 and ObjectLabKit Calculator1.2111
Use Java8 and Parallel Stream0.6017


So it looks like, when using single thread, that the RAW use of stream.map and reduce is the most efficient but one has to remember how to write it:

  final BigDecimal reduce = list.stream()
        .map(Test::getValue)
        .reduce(BigDecimal.ZERO
                (a, b) -> b != null ? a.add(b) : a);

Using the parallelStream (when suitable) reduces the average to 0.5ms but the max is 18ms
  final BigDecimal reduce = list.parallelStream()
        .map(Test::getValue)
        .reduce(BigDecimal.ZERO
                (ab) -> b != null ? a.add(b) : a);


Full code available here at GitHub Gist

ObjectLab Kit 1.3.0 released

We are delighted to announce the release of ObjectLab Kit 1.3.0.

See http://objectlabkit.sf.net

The release is available on Maven Central or Under files in SourceForge.

The Source Code lives at GitHub: http://github.com/appendium/objectlabkit

Feel free to fork and contribute!

This release fixes a couple of bugs but also:

  1. includes a JDK8 module using java.time.LocalDate; it is the only module requiring JDK8
  2. includes the first official release of ObjectLab Utils a small library with
  • Some caches with expiring/timeout but unlike Guava or EHCache, the cache can be refreshed in its entirety in one go; this is suitable only if you can hold the entire dataset in memory; on the plus side, you would hit the generator/DB only once.
  • Lots of small utilities for BigDecimal, Integer, Boolean and Collection, mainly to deal with nulls.  And if you deal with BigDecimal, Total, Average and WeightedAverage classes will be very useful.
  • ConsoleMenu a way to create user menus for a console/command line application.
Enjoy!

Benoit & the team.

FlatPack 3.4.0 released

Dear All

It is with great pleasure to announce that, after a while one must admit, we have released a new version of FlatPack, v 3.4.0

See FlatPack Website for more information.

Or the change log

The libraries are available on Maven Central and still only required JDK 1.5.

Note that the next release will jump directly to Java8 as we will make use of some cool stream functionalities and Autocloseable features (jdk7).

here is an example of what is coming with 4.0:


Enjoy!

Friday, 12 March 2010

Sonar and BlackDuck.com for ObjectLab Kit.

A big thank you to Simon from SonarSource.org to include ObjectLab Kit in their demo site.

Check this out: http://nemo.sonarqube.org/dashboard/index/250253

But we're going to make it better... reach a higher % of compliance...

Also thanks to ohloh.net

https://www.openhub.net/p/objectlabkit

If you are using it... vote for it!

And, yepee, I am ranked 2,400 or something out of 315,000...

https://www.openhub.net/accounts/benoitx

Whatever that means.

Enjoy!

Thursday, 11 March 2010

FlatPack 3.2.0 is released!

FlatPack on SourceForge: a Java (1.4+) flat file parser that handles CSV, fixed length and custom delimiters. The formats are configured in XML, it is fast and released under Apache license 2.0.

http://flatpack.sf.net


Changes in this version include:

New Features:

o Added a getBigDecimal method on DataSet.

Fixed bugs:

o Fixed SF Bug 1869636. The parameters for the XML Map and data file were reversed in the BuffReaderDelimParser.
o Stopped the fixed width parser from removing leading spaces in a data element. Added the ParserUtils.rTrim() method.
o Added check for duplicate column names when using file header for column names.
o Applied patch from Dirk Olmes to prevent duplicate column names in the XML
mapping. IllegalArgumentException is now thrown if a duplicate column name exists in the map. Thanks Dirk...
o doParse() on DBFixedLengthParser was returning a null and was never getting a DataSet returned

Enjoy!

Saturday, 14 March 2009

StatCVS 0.5.0 Beta is out

A new StatCVS library is available for BETA testing at:

StatCVS retrieves information from a CVS repository and generates various tables and charts describing the project development.

http://statcvs.sf.net/beta/statcvs.jar

Site: http://statcvs.sf.net/beta

Manual:
http://statcvs.sourceforge.net/beta/manual.html

The biggest changes are:
- Charts are now quite configurable: colors, size, copyright text, etc
- a Twitter Integration: link, embedding last tweets via Flash or HTML

have a go!

Enjoy

Benoit

Sunday, 4 May 2008

StatCVS 0.4.0 released!

Hi All,

Quick post to let you know that StatCVS, the new member of the family (but by all means not a baby given that it has been around since 2002!) has a new release version 0.4.0.

The release is available on http://statcvs.sf.net

The changes are described here: http://statcvs.sourceforge.net/changes-report.html

Thanks to everyone who participated by sending patches, suggestions and checking the beta!

Enjoy!

Benoit