按天拆分java.util.Date集合

请问你能帮帮我吗。 我无法弄清楚算法。

我有一个已排序的日期集合,例如ArrayList,如下所示:

Wed Jan 22 00:00:00 MSK 2014 Wed Jan 22 00:30:00 MSK 2014 Wed Jan 23 01:00:00 MSK 2014 Wed Jan 23 01:30:00 MSK 2014 Wed Jan 23 02:00:00 MSK 2014 Wed Jan 24 02:30:00 MSK 2014 Wed Jan 24 03:00:00 MSK 2014 Wed Jan 24 03:30:00 MSK 2014 Wed Jan 24 04:00:00 MSK 2014 Wed Jan 28 04:30:00 MSK 2014 Wed Jan 28 05:00:00 MSK 2014 

我需要此列表的另一个版本,按天分组(从00:00:00到23:59:59),因此它可能是列表数组,如List<List> 。 在示例之后,它应该是大小为4的列表,第二个Object ==

 List {Wed Jan 23 01:00:00 MSK 2014; Wed Jan 23 01:30:00 MSK 2014; Wed Jan 23 02:00:00 MSK 2014; } 

看似简单的任务。 但我找不到方便的方法来解决它。 提前致谢。

更新根据TEXHIK的回答,宽度JDK 7可以这样做:

  public List<List> split(List value) { List<List> result = new ArrayList(); int day = value.iterator().next().getDate(); List newListEntry = new ArrayList(); for (Date date : value) { if (date.getDate() == day) { newListEntry.add(date); } else { day = date.getDate(); result.add(newListEntry); newListEntry = new ArrayList(); newListEntry.add(date); } } result.add(newListEntry);//because the last sublist was not added return result; } 

没关系,除非它是java.util.Date的弃用方法。 很高兴看到使用Java 8或Joda Time的答案。

如果您对UTC时代感到满意,生活会变得更加简单:

  • 毫秒 – 自从unix-epoch开始于一天的边界,所以你可以分开
  • 每天都是24小时,这在很多情况下很方便(例如,如果您正在对数据进行分析)

在这种情况下,您可以使用以下内容:

 long millisPerDay = TimeUnit.DAYS.toMillis(1); Map> datesByDay = new HashMap<>(); for (Date date : dates) { long day = date.getTime() / millisPerDay; List dayDates = datesByDay.get(day); if (dayDates == null) { dayDates = new ArrayList<>(); datesByDay.put(day, dayDates); } dayDates.add(date); } 

当然,例如来自Guava的Multimap将使这更简单:

 long millisPerDay = TimeUnit.DAYS.toMillis(1); Multimap datesByDay = ArrayListMultimap.create(); for (Date date : dates) { long day = date.getTime() / millisPerDay; datesByDay.put(day, date); } 

公共类SortBydate {

 public static void main(String args[]) { ArrayList ls = new ArrayList(); HashMap> has = new HashMap>(); SimpleDateFormat format1=new SimpleDateFormat("dd/MM/yyyy/HH/mm/ss"); try { ls.add(format1.parse("22/01/2014/00/00/00")); ls.add(format1.parse("22/01/2014/00/30/00")); ls.add(format1.parse("23/01/2014/01/00/00")); ls.add(format1.parse("23/01/2014/01/30/00")); ls.add(format1.parse("23/02/2014/02/00/00")); ls.add(format1.parse("24/02/2014/02/30/00")); ls.add(format1.parse("24/02/2014/03/00/00")); ls.add(format1.parse("24/02/2014/03/30/00")); ls.add(format1.parse("24/02/2014/04/00/00")); ls.add(format1.parse("28/02/2014/05/00/00")); ls.add(format1.parse("28/02/2014/00/30/00")); } catch (ParseException e) { e.printStackTrace(); } Iterator it = ls.listIterator(); while(it.hasNext()) { Date dt = it.next(); String date = dt.getDate() +"," + dt.getMonth() + "," + dt.getYear(); if(has.containsKey(date)) { has.get(date).add(dt); } else { has.put(date, new ArrayList()); has.get(date).add(dt); } } Set set = has.entrySet(); it = set.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); System.out.println(entry.getValue()); } } 

}

很高兴看到使用Java 8或Joda Time的答案。

我将混合使用Java 8 Time LibraryGoogle Guava's Multimap

 List list=new ArrayList(); // Add the Sorted LocalDateTime into it ........... Multimap builder=ArrayListMultimap.create(); list.forEach(local -> builder.put(local.getDayOfMonth(),local)); 

现在只需迭代Multimap并查看所需的输出

 Set keySet = builder.keySet(); Iterator keyIterator = keySet.iterator(); while (keyIterator.hasNext() ) { Integer key = (Integer)keyIterator.next(); List values=(List) builder.get(key); System.out.println(values); } 

对于输入

 2015-02-18T16:33:49.114 2015-02-18T17:33:49.114 2015-02-18T18:33:49.114 2015-02-18T19:33:49.114 2015-02-18T20:33:49.114 2015-02-19T17:33:49.114 2015-02-19T18:33:49.114 2015-02-19T19:33:49.114 2015-02-19T20:33:49.114 

输出:

 [2015-02-18T16:33:49.114, 2015-02-18T17:33:49.114, 2015-02-18T18:33:49.114, 2015-02-18T19:33:49.114, 2015-02-18T20:33:49.114] [2015-02-19T17:33:49.114, 2015-02-19T18:33:49.114, 2015-02-19T19:33:49.114, 2015-02-19T20:33:49.114] 

从Java 8的角度来看,这个答案可能很有趣。 此示例使用流API以及java.time.*

  public static List> split(List value) { return new ArrayList<>(value.stream().sorted().collect( Collectors.groupingBy( // Group by LocalDate converted from Date d -> d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), // Group into a LinkedHashMap to preserve encounter order LinkedHashMap::new, // We want the grouped elements in a List Collectors.toList())).values()); } 

这是一个相同的unit testing:

  @Test public void testSplit() { final int TEST_DAYS = 9; final int TEST_HOUR_STEP = 8; final int TEST_DATES_PER_DAY = 24 / TEST_HOUR_STEP; // Generate test data List dateList = new ArrayList<>(); final int yy = 2015; final int mm = 2; for (int dd = 1; dd < 1 + TEST_DAYS; ++dd) { for (int h = 0; h < 24; h += TEST_HOUR_STEP) { LocalDateTime ldt = LocalDateTime.of(yy, mm, dd, h, 0, 0); dateList.add(Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant())); } } List> splitDates = split(dateList); // We should have TEST_DAYS lists assertEquals(TEST_DAYS, splitDates.size()); for (List ld : splitDates) { // Each list should have TEST_DATES_PER_DAY elements assertEquals(TEST_DATES_PER_DAY, ld.size()); // Each list should have a single distinct element when converted to LocalDate assertEquals(1, ld.stream() .map(d -> d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) .distinct() .count()); } } 

尝试填写新的列表,直到这一天等于。 由于您的原始列表已排序,因此应该没有错误。

 int day; List newListEntry = new ArrayList(); Iterator sourceIterator = your_original_list.iterator(); while(iterator.hasNext()) { Date date = iterator.next(); if (date.getDate() == day) newListEntry.add(date); else { day = date.getDate(); your_new_list.add(newListEntry); newListEntry = new ArrayList(); newListEntry.add(date); } } your_new_list.add(newListEntry);//because the last sublist was not added