【问题标题】:Merging keys of a HashMap合并 HashMap 的键
【发布时间】:2021-05-06 15:00:56
【问题描述】:

我正在从数据库中获取数据并制作如下地图:

   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())));

现在的问题是,对于其中一个通道,运行日期是每小时一次,即通道上的批处理每小时运行一次,因此从数据库中获取的特定源的运行日期采用 yyyyMMddHH 的形式,而不是 yyyyMMdd。

我的代码适用于运行日期为 yyyMMdd 格式的频道,我上面的地图示例 (groupDatesByChannel) 如下所示:

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

我想为每小时运行日期的频道制作此映射。

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

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

即我想合并所有相同的日期,无论是 yyyyMMddHH 还是 yyyyMMdd fromat。

【问题讨论】:

  • 我不确定您要的是什么,但您是否“简单地”采用某种转换方法来接受MyBO::getChannelName 发出的任何内容......并将其转换为首选格式?

标签: java java-8 functional-programming


【解决方案1】:

实现这一目标的最简单方法是仅将 DateTime 的前 8 个字符用于分组。

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

【讨论】:

  • 谢谢,是的,这似乎是一个非常好的解决方案,但在下面的代码中,不起作用(编译)Map&lt;String, List&lt;String&gt;&gt; groupDatesByChannel = data .parallelStream().collect( Collectors.groupingBy(MyBO::getChannelName, Collectors.mapping(myBO -&gt; myBO.getRunDate().substring(0,8), Collectors.toList())));
【解决方案2】:

以下代码已经过测试并且可以正常工作。

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;

}

逻辑很简单

  1. 创建一个新的 HashMap
  2. 从原始数据中读取每个键值对
  3. 修剪键以仅包含日期值
  4. 使用 trimmedKey 将值插入新的 HashMap

您可以运行代码并自行检查。对我来说效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    相关资源
    最近更新 更多