你能帮帮我吗?我无法弄清楚算法。
我有一个排序的日期集合,例如像这样的 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 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));
现在只需迭代多重贴图并查看所需的输出
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