我有一个已排序的Dates集合,例如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的列表,第二个Object ==
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的答案。
答案 0 :(得分:1)
如果您对UTC时代感到满意,生活会变得更加简单:
在这种情况下,您可以使用以下内容:
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
,例如来自Guava,将使这更简单:
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);
}
答案 1 :(得分:0)
尝试填写新的列表,直到这一天等于。由于您的原始列表已排序,因此应该没有错误。
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
答案 2 :(得分:0)
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());
}
}
}
答案 3 :(得分:0)
很高兴看到使用Java 8或Joda Time的答案。
我会使用Java 8 Time Library
和Google 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));
现在只需迭代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]
答案 4 :(得分:0)
从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());
}
}