简体   繁体   中英

Merging keys of a HashMap

I am fetching data from a database and making a map as below:

   List<MyBO> data = callDatabase();

   //here I am grouping the channels by run date
    Map<String, List<String>> groupDatesByChannel = data .parallelStream().collect(
                Collectors.groupingBy(MyBO::getChannelName,
                        Collectors.mapping(MyBO::getRunDate, Collectors.toList())));

Now the problem is that for one of the channels, run date is hourly ie the batch on channel run every hour so for that particular source run dates fetched from data base are in the form of yyyyMMddHH as opposed to yyyyMMdd.

my code works fine for channels where run date is in yyyMMdd format and example of my map above (groupDatesByChannel) is like:

Channel_2[20200101 , 20200103 , 20200107],
Channel_5[20200103 ]
Channel_7[20200102 , 20200104 ]

I want to make this mapping for the channel where run dates are hourly.

Channel_1[**2020010100,2020010101...2020010123,20200101**, 20200102, 20200104 ],
Channel_2[20200101 , 20200103 , 20200107],
Channel_5[20200103 ]
Channel_7[20200102 , 20200104 ]   

to

    Channel_1[**20200101**, 20200102, 20200104 ],
    Channel_2[20200101 , 20200103 , 20200107],
    Channel_5[20200103 ]
    Channel_7[20200102 , 20200104 ]

ie I want to merge all same dates whether its in yyyyMMddHH or yyyyMMdd fromat.

The following code is tested and working fine.

public static Map<String, List<String>> mergeData(Map<String, List<String>> originalData){

    Map<String, List<String>> mergedData = new HashMap<String, List<String>>();

    for(String key : originalData.keySet()){
        // Cleaning the key string. Removing *'s
        String trimmedKey = key.replaceAll("\\*","");
        // Trimming the key string. Trimming the hour digits, so that key will only contain date value
        String dateOnlyKey = trimmedKey.substring(0,8);
        // If mergedData already has the key, add values to the list.
        if(mergedData.containsKey(dateOnlyKey)){
            // Adding directly to the list may create duplicate entries. So, appending all data to HashSet and writing back to list
            // If having duplicates is ok, next two lines can be ommitted and third line would be mergedData.get(dateOnlyKey).addAll(originalData.get(key));
            Set<String> channels = new HashSet<String>(mergedData.get(dateOnlyKey));
            channels.addAll(originalData.get(key));
            mergedData.put(dateOnlyKey, new ArrayList<String>(channels));
        }
        // If mergedData doesn't have the key, add the new entry
        else{
            mergedData.put(dateOnlyKey, originalData.get(key));
        }
    }
    System.out.println(mergedData.entrySet());
    return mergedData;

}

The logic is simple

  1. Create a new HashMap
  2. Read each key-value pair from original data
  3. Trim the key to contain only date value
  4. Insert the value into new HashMap with the trimmedKey

You can run the code and check for yourself. Worked fine for me.

The simplest way to achieve that will be to simply take only the first 8 characters of your DateTime for the grouping.

Map<String, List<String>> groupDatesByChannel = data .parallelStream().collect(
            Collectors.groupingBy(myBO -> myBO.getChannelName().substring(0,8),
                    Collectors.mapping(MyBO::getRunDate, Collectors.toList())));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM