Java 8 - New features && Financial reconciliation applications

Keywords: Java Lambda

Background:

1. In financial industry, there is usually reconciliation.
2. The essence of reconciliation is to compare the transaction records of both parties.
3. Both sides have transaction records. Comparing [status & amount], we will only focus on Kazakhstan. 
3.1. The same amount of status is recorded as success and vice versa as failure. 
4. If one party has something that the other does not have, we shall write it down as long or short.

New features in Java 8, in this blog, the main application of new Java features is Function & Stream.

Account reconciliation, usually with upstream data [reList], and local data [loList]. I assume that its data structure is List < Map >.

First, define a BiFunction, two parameters, and one return value. remote is the upstream data and local is the local data.

The code is as follows:

static BiFunction<List<Map>, List<Map>, Map> diff = (remote, local) -> { null };

Usually we nest loops and traverse two sets. This operation is too traditional, and it would be a bit foolhardy if both sets were millions in length.

Let's take a cue and turn one of our collections into a dictionary.

Why turn List into Map? Wise buddies already understand. Because nested loops can be split, reducing the order of magnitude.

We just need to loop through a List, take out the order number, and then take out the local order [map value] from the dictionary [Map] according to the order number [map key].

We have assumed the data structure, so we use the transaction order number as the key of the Map and the transaction order as the value.

We can take advantage of the new features in Java 8. The code is as follows:

Map<String,Map> localMap =
 local.stream().collect(Collectors.toMap(map -> map.get("orderNo").toString(), Function.identity()));

The Collectors.toMap(keyFunc, valFunc) method receives parameters as Lambda expressions, and its function is obviously to turn collections into dictionaries [Maps].

As for the dictionary key, where does value come from? From objects in a collection. How come?

Write a Function yourself to implement it. Anyway, I'll let you pass two Functions to implement key and value respectively.

So keyFunc is used to generate the keys of our transformed Map. valFunc, as we all know, is used to generate the value s of our Map.

map.get("orderNo").toString(), I understand, is to take the order number from the order record and then use it as the key of the Map.

What about Function.identity()? Don't rush, that is to say, I will return whatever parameter you pass in.

We take orders as Map values, so of course you can also write Function.identity() as map - > map!

At this point, we have turned a List into a Map.

The cute bars companion will say, you say so much, so complex. It's easy for me to iterate through List directly and then convert to Map.

Well, actually I will. The code is as follows:

    public Map toMap(List<Map> loList){
        Map reslut = new HashMap();
        for (Map map: loList){
            reslut.put(map.get("orderNo"), map);
        }
        return reslut;
    }

However, Benbo is to chat with you about new features. So barjing, don't refute me anymore.

Okay, let's get to the point. Let's go on.

We traverse the upstream data and then compare the upstream data with the local data. Come and cycle.

    public void diff(List<Map> reList){
        /**
         * The previous step converted the local order from List to Map
         */
        Map<Object,Map> loMaps = new HashMap();
        for (Map reMap : reList){
            //reMap for upstream orders
            Object orderNo = reMap.get("orederNo");
            //loMap Local Order
            Map loMap = loMaps.get(orderNo);
            /**
             * Come on, compare the upstream order [reMap] with the local order [loMap].
             * This specific process of comparison is reconciliation, comparison of amount, status, time and so on.
             * Then the results of the accounts are put into storage or landed.
             */
        }
    }

The reconciliation is done. Ha-ha-ha, perfect. ... Wait a minute. There seems to be something wrong. Aren't we going to use new features?

Wait a minute. Let me meditate for a second. Okay, here's the code.

    public void diff(List<Map> reList){
        /**
         * The previous step converted the local order from List to Map
         */
        Map<Object,Map> loMaps = new HashMap();
        reList.stream().forEach(reMap -> {
            //reMap for upstream orders
            Object orderNo = reMap.get("orederNo");
            //loMap Local Order
            Map loMap = loMaps.get(orderNo);
            /**
             * Come on, compare the upstream order [reMap] with the local order [loMap].
             * This specific process of comparison is reconciliation, comparison of amount, status, time and so on.
             * Then the results of the accounts are put into storage or landed.
             */
        });
    }

Wise buddies have found out, what's the difference between TM? Is it for instead of. stream().forEach?

Well, big-breasted brother, don't rush. Listen to me slowly. list.stream() is a new feature that streams collections.

After the hooliganism, you can have a lot of hooliganism. As for the specific hooliganism posture, you need to develop it slowly by yourself.

... Well, it's not hooliganism, it's fluidization...

Actually, I'm still a bit of a man of integrity. Now that BiFunction has been mentioned at the beginning, how can it be possible to stop nagging?

It's too scattered. It seems a little confused. Let's sort it out again.

    /**
     * Reconciliation
     * <ol>
     *     <li>remote Set of upstream orders</li>
     *     <li>local Set of upstream orders</li>
     *     <li>Let's assume that the object in the collection is Map, or, of course, your custom JavaBean, such as OrderInfo or something.</li>
     * </ol>
     */
    static BiFunction<List<Map>, List<Map>, Map> diff = (remote, local) -> {
        /**
         * Convert local orders from List to Map
         * <br>Take order number as key and order information as value
         */
        Map<String,Map> loMaps =
                local.stream().collect(Collectors.toMap((map) -> map.get("orderNo").toString(), map -> map));
        /**
         * Streaming Upstream Data
         */
        Stream<Map> stream = remote.parallelStream();
        /**
         * Reconciliation result
         */
        Map result = new ConcurrentHashMap();
        stream.collect(Collectors.toList()).forEach(reMap->{
            //reMap for upstream orders
            Object orderNo = reMap.get("orederNo");
            //loMap Local Order
            Map loMap = loMaps.get(orderNo);
            /**
             * Come on, compare the upstream order [reMap] with the local order [loMap].
             * This specific process of comparison is reconciliation, comparison of amount, status, time, length of money and so on.
             * Then the results of the accounts are put into storage or landed.
             * You can also deposit the result of the account.
             * If there is a business need, the account results will be responded to by the caller to deal with it separately.
             */
        });
        /**
         * Return the reconciliation results
         */
        return result;
    };

Do you think, buddies, that you might as well write this BiFunction as I do? There's some truth in it.

We have to use new characteristics, so old iron, do not care too much about these details, BiFunction naturally has its place.

So, we all know how to call the method, and how to call the BiFunction?

See the code:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo {

    /**
     * Reconciliation
     * <ol>
     *     <li>remote Set of upstream orders</li>
     *     <li>local Set of upstream orders</li>
     *     <li>Let's assume that the object in the collection is Map, or, of course, your custom JavaBean, such as OrderInfo or something.</li>
     * </ol>
     */
    static BiFunction<List<Map>, List<Map>, Map> diff = (remote, local) -> {
        /**
         * Convert local orders from List to Map
         * <br>Take order number as key and order information as value
         */
        Map<String,Map> loMaps =
                local.stream().collect(Collectors.toMap((map) -> map.get("orderNo").toString(), map -> map));
        /**
         * Streaming Upstream Data
         */
        Stream<Map> stream = remote.parallelStream();
        /**
         * Reconciliation result
         */
        Map result = new ConcurrentHashMap();
        /**
         * Traversing upstream orders, running reconciliation business
         */
        stream.collect(Collectors.toList()).forEach(reMap->{
            //reMap for upstream orders
            Object orderNo = reMap.get("orederNo");
            //loMap Local Order
            Map loMap = loMaps.get(orderNo);
            /**
             * Come on, take the upstream order [reMap] and the local order [loMap] to compare.
             * This specific process of comparison is reconciliation, comparison of amount, status, time, length of money and so on.
             * Then the results of the accounts are put into storage or landed.
             * You can also deposit the result of the account.
             * If there is a business need, the account results will be responded to by the caller to deal with it separately.
             */
        });
        /**
         * Return the reconciliation results
         */
        return result;
    };

    public static void main(String[] args) {
        //Upstream order
        List<Map> re = new ArrayList();
        //Local order
        List<Map> lo = new ArrayList();

        /**
         * No, let's pretend they have millions of data.
         */

        System.out.println("Reconciliation begins");
        Map map = diff.apply(re, lo);
        System.out.println("Reconciliation completion");
        System.out.println("Reconciliation result" + map);

    }
}

All right! The code is all posted.. I should have nothing to say.

But a careful little friend asked me why you used stream.forEach(...) first and then stream. collectors. toList (). forEach (...) when you traversed upstream data.

Very well, you've found all these details.

In fact, the key lies in the fluidization mode.

[Stream < Map > stream = remote. parallelStream ();] This is a parallel stream.

Stream < Map > stream = remote. stream ();} This is a serial stream

[stream. collect (Collectors. toList (). forEach] is designed to ensure thread safety in parallel streams.

Well, I don't know if I've made myself clear. More applications of new features, there are more, we share more!

Posted by bandit8 on Tue, 07 May 2019 02:55:38 -0700