

Reduce operation in Java 8 - sun123
http://vinothonsoftware.com/2015/04/20/reduce-operation-in-java-8/

======
pmlamotte
We have a poorly written Java client app that has a large number of resources
it has to pull down from S3 at startup time. As a small side project I built
up a large subset of it from scratch with clojure, mostly to get my feet wet
in it. By compartmentalizing everything, I realized how I could simply swap
out some of my map statements for pmap, add some async, and I was able to have
my new implementation starting up in 1s as opposed to 30s (our problem was
more latency than actual bandwidth).

I decided to take a look at Java 8's streams, and porting that speed over
turned out to be pretty straightforward. The first step was to swap out our
iterative, awful thread management download code with parallelStream. When I
say awful, I mean it was increasing and decreasing a non-thread-safe static
counter and busy waiting for it to hit 0, among other confusing constructs. I
also took the time to refactor out several if statements and other code with
filter and map statements.

Java 8 lambdas also worked well in that a lambda can be passed in where any
Functional Interface is required (the interface has one function), so long as
the lambda has the same arity. I was able to use this to have a list of
Runnables (basically function/method pointers) that I ran in parallelStreams
where previously it was iterative. It looked more verbose than but still
comparable to my clojure code.

Finally, I had some tasks that took a long time but were not required at
startup since you only needed the resources for specific functions in the app
long after you loaded a project. I swapped those out with
CompletableFuture.supplyAsync(), as well as took in a callback function for
when it completed. If you did manage to need that resource before it finished
loading, you would get a loading message until the callback was called.

Granted, a lot of what the app was doing beforehand could have been done much
better, such as with ThreadPoolExecutor (and I did see some complaints about
efficiency with parallelStream). However, the java8 way came out pretty clean
as far as java goes, and I was able to add more/better functionality while
still having less code overall. While there is still a lot of improvement that
could be done to the streams, they worked out pretty well for my use case.

------
oelang
And in scala it's just listOfTxnAmounts.sum or listOfTxnAmounts.max, long live
typeclasses (but that's too complicated for 'normal' programmers right?)

------
ajanuary
Stream already has a max method:

    
    
        return listOfTxnAmounts.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
    

(They behave differently for a list that only has negative numbers, but it
seems like that isn't a part of the domain anyway)

------
yarper
I know this is supposed to show us about cool java 8 features, but what it's
actually reminding me is how jarring BigDecimal is without operator
overloading.

~~~
ajanuary
Having a method allows sum to be written as:

    
    
        return listOfTxnAmounts.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
    

rather than what you have to do for operators(unless there is a way of
referencing the operators I haven't found):

    
    
        return listOfTxnAmounts.stream().reduce(0, (a, b) -> a + b);

~~~
yarper
Sure, the other way is this;

    
    
        Arrays.stream(new int[] { 1,2,3 }).sum();

