ConcurrentHashMap终于安排上了--按半年统计用户访问量

前言

需求查询系统登录日志表, 按半年为周期统计用户访问量

这里按半年统计用户访问量是指从最早的一条记录到当前时间的所有记录按半年这个周期进行统计, mysql中有统计季度的函数Quarter, 以下是按季度统计的sql和查询结果, 按正序排:

SQL

SELECT
    CONCAT(
        YEAR (create_time),
        QUARTER (create_time)
    ) m,
    COUNT(
        DATE_FORMAT(create_time, '%Y-%m')
    ) count
FROM
    login_log AS a
GROUP BY
    m
ORDER BY
    m ASC

查询结果

 

 

service层封装后的结果为:

List<StatisticsViewVo> resultVos = getQuarterViewVos(sourceList, calendar);

目标结果

{
    "success": true,
    "payload": {
        "data": [
            {
                "m": "2019上半年",
                "count": 0
            },
            {
                "m": "2019下半年",
                "count": 3
            },
            {
                "m": "2020上半年",
                "count": 6
            },
            {
                "m": "2020下半年",
                "count": 11
            }
        ]
    }
}

思路

  1. 将list中的vo对象中的m和count按键值对存入map中

  2. 在遍历list时根据map的containsKey方法判断获取对应key的value

  3. 将该value存入对应的上半年或下半年统计数中

  4. 删除统计过的元素

不啰嗦了, 看代码吧, 略low, 好在能用..

代码

resultVos = getQuarterViewVos(sourceList, calendar);
// 遍历resultVos,存入map
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
for (StatisticsViewVo vo : resultVos) {
    map.put(vo.getM(), vo.getCount());
}
List<StatisticsViewVo> resultList = Lists.newArrayList();
// 再次遍历resultVos
if (CollectionUtils.isNotEmpty(resultVos)) {
    Iterator<StatisticsViewVo> iterator = resultVos.iterator();
    while (iterator.hasNext()) {
        StatisticsViewVo vo = iterator.next();
        String yearAndQuarter = vo.getM();
        String year = yearAndQuarter.substring(0, 4);
        String year1 = year + "1";
        String year2 = year + "2";
        String year3 = year + "3";
        String year4 = year + "4";
        String ayear = year + "上半年";
        String pyear = year + "下半年";
        int acount = 0;
        int pcount = 0;

        // 统计该year的所有季度的访问量,并将12季度统计到上半年,34季度统计到下半年
        if (map.containsKey(year1)) {
            acount += map.get(year1);
        }
        if (map.containsKey(year2)) {
            acount += map.get(year2);
        }
        if (map.containsKey(year3)) {
            pcount += map.get(year3);
        }
        if (map.containsKey(year4)) {
            pcount += map.get(year4);
        }

        if (map.containsKey(year1) || map.containsKey(year2)) {
            StatisticsViewVo avo = new StatisticsViewVo();
            avo.setM(ayear);
            avo.setCount(acount);
            resultList.add(avo);
        }
        if (map.containsKey(year3) || map.containsKey(year4)) {
            StatisticsViewVo pvo = new StatisticsViewVo();
            pvo.setM(pyear);
            pvo.setCount(pcount);
            resultList.add(pvo);
        }

        // 移除map中以该year开头的key,因为需要多次遍历不能用迭代器,更不能用普通HashMap因为会抛并发异常
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            String key = entry.getKey();
            if (key.startsWith(year)) {
                map.remove(key);
            }
        }
    }

 

posted @ 2020-08-19 00:58  习惯沉淀  阅读(481)  评论(0编辑  收藏  举报