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).<p>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.<p>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.<p>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.<p>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.
And in scala it's just listOfTxnAmounts.sum or listOfTxnAmounts.max, long live typeclasses (but that's too complicated for 'normal' programmers right?)
Stream already has a max method:<p><pre><code> return listOfTxnAmounts.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
</code></pre>
(They behave differently for a list that only has negative numbers, but it seems like that isn't a part of the domain anyway)
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.