在 HashMap 构造中按天对时间戳列表(日期对象)进行分组

Group a List of timestamps (Date objects) by day in a HashMap construct

我们从时间戳列表开始,它们是 Date 对象。我们需要对属于唯一一天的所有时间戳进行分组。例如,当用户登录到我们的服务器时,时间戳将添加到单个列表中。我们希望能够解析这个列表并分离属于同一天的所有 Date 对象。最终目标是能够在 UI 上轻松显示按天分隔的所有登录,以及显示每天发生的登录次数。

最终的 HashMap 构造应该如下所示:

Key                          List<Date> 

2018-07-11 
                  2018-07-11 08:14:08.540000 
                  2018-07-11 10:46:23.575000 

2018-07-12  
                  2018-07-12 12:51:48.928000 
                  2018-07-12 13:09:00.701000 
                  2018-07-12 16:04:45.890000 

2018-07-13 
                  2018-07-13 14:14:17.461000 

这是我们想出的解决方案。 parseTimeStamps 方法获取 timeStamps 的列表对其进行迭代,并使用 Calendar 对象将小时、分钟、秒和毫秒设置为 0,从而只为我们提供日期。然后,我们检查我们的 groupedUserLogins HashMap 以查看它是否包含具有该日期的键。如果没有,我们将创建一个包含那一天的键,并创建一个新的 Date 对象列表作为与该键关联的值。随后,我们将时间戳 (ts) 添加到与那天关联的列表中。

在下一次迭代中,如果我们在 HashMap 中遇到与我们剥离的 Calender 对象匹配的键,我们会立即将该时间戳 (ts) 添加到与该现有日期关联的列表中。

我创建了以下方法,其中 returns 一个 HashMap>,其中键是日期对象,值是日期对象列表。该方法接受时间戳列表并按天对它们进行分组。然后 returns 上述 HashMap 构造中的那些分组时间戳。

 public class GroupDatesByDay {

    HashMap<Date, List<Date>> groupedUserLogins = new HashMap<Date, List<Date>>();
    Calendar cal = Calendar.getInstance();

    public HashMap<Date, List<Date>> parseTimeStamps(List<Date> timeStamps) {

    DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS", Locale.US);
    List<Date> timeStamps = new ArrayList<Date>();

        for (Date ts : timeStamps) {

            cal.setTime(ts);
            cal.set(cal.HOUR_OF_DAY, 0);
            cal.set(cal.MINUTE, 0);
            cal.set(cal.SECOND, 0);
            cal.set(cal.MILLISECOND, 0);

            if (!groupedUserLogins.containsKey(cal.getTime())) {

                groupedUserLogins.put(cal.getTime(), new ArrayList<Date>());
            }
            groupedUserLogins.get(cal.getTime()).add(ts);
        }

        keySet = groupedUserLogins.keySet();
        keyList.addAll(keySet);
        return groupedUserLogins;
    }
}

我们最终得到 groupedUserLogins,它现在方便地将所有唯一日期存储为指向包含我们时间戳的列表的键,作为 Date 对象。这种数据结构的最大优点是键和值仍然是 Date 对象,为我们提供了未来的灵活性。

请随时提供替代解决方案,或改进我提供的解决方案。

这是 java8 的实现方式。

List<LocalDateTime> loginTimes = Arrays.asList(LocalDateTime.of(2018, 5, 7, 8, 10),
        LocalDateTime.of(2018, 5, 7, 9, 15, 20), LocalDateTime.of(2018, 6, 22, 7, 40, 30));
Map<LocalDate, Long> loginCountByDate = loginTimes.stream()
        .collect(Collectors.groupingBy(LocalDateTime::toLocalDate, Collectors.counting()));

先将登录次数按日期分组,然后统计每个日期的登录次数。这是我可以建议的最佳解决方案,但它要求您使用 Java8.

这是输出。

{2018-05-07=2, 2018-06-22=1}