按天拆分 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<Date>> .按照示例,它应该是大小为 4 的列表,第二个对象 ==

List<Date> {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<Date>> split(List<Date> value) {
        List<List<Date>> result = new ArrayList<>();
        int day = value.iterator().next().getDate();
        List<Date> 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<Long, List<Date>> datesByDay = new HashMap<>();
for (Date date : dates) {
    long day = date.getTime() / millisPerDay;
    List<Dates> dayDates = datesByDay.get(day);
    if (dayDates == null) {
        dayDates = new ArrayList<>();
        datesByDay.put(day, dayDates);
    }
    dayDates.add(date);
}

当然,Multimap,例如来自番石榴,会使这更简单:

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

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

  public static List<List<Date>> split(List<Date> 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());
  }

这是相同的单元测试:

  @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<Date> 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<List<Date>> splitDates = split(dateList);
    // We should have TEST_DAYS lists
    assertEquals(TEST_DAYS, splitDates.size());
    for (List<Date> 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());
    }
  }

public class SortBydate {

public static void main(String args[])
{
    ArrayList<Date> ls = new ArrayList<Date>();
    HashMap<String , ArrayList<Date>> has = new HashMap<String , ArrayList<Date>>();

      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<Date> 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<LocalDateTime> list=new ArrayList<LocalDateTime>();
// Add the Sorted LocalDateTime into it ...........
Multimap<Integer, LocalDateTime> builder=ArrayListMultimap.create();
list.forEach(local -> builder.put(local.getDayOfMonth(),local));

现在只需迭代多重贴图并查看所需的输出

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]

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

int day;
List<Date> newListEntry = new ArrayList<Date>();
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<Date>();
       newListEntry.add(date);
    }
}
your_new_list.add(newListEntry);//because the last sublist was not added

最新更新