0

为什么集合不从排序列表中删除重复项?我已按第一行显示的升序对日期进行了排序,但该集合并未删除重复项。这是为什么 ?程序打印:
[Mon Apr 20 12:27:47 CDT 2009, Mon Apr 20 12:27:47 CDT 2009, Sun Dec 20 12:27:47 CST 2009] [Sun Dec 20 12:27:47 CST 2009, 2009 年 4 月 20 日星期一 12:27:47 CDT 2009,4 月 20 日星期一 12:27:47 CDT 2009]

不应该创建一个集合从集合中删除重复的日期吗?

    def void testLoadDoc()
     {
     Date date1 = getCurrentDate(3,20,2009)
     Date date2 = getCurrentDate(11,20,2009)
     Date date3 = getCurrentDate(3,20,2009)


     List<Date> dates = new ArrayList<Date>();
     dates.add(date2);
     dates.add(date1);
     dates.add(date3);

     Collections.sort(dates, new CurrencyDateComparator());
     Set uniqueDates = new HashSet(dates)

     println dates
     println uniqueDates

 }


 private Date getCurrentDate(int month, int day, int year)
 {

     Calendar cal = Calendar.getInstance();
     cal.set(YEAR, year);
     cal.set(MONTH, month);
     cal.set(DAY_OF_MONTH, day);
     return cal.getTime();

 }
}

class CurrencyDateComparator implements Comparator
{
    /* (non-Javadoc)
     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
     */
    public int compare(Object arg0, Object arg1)
    {
        Date p = (Date) arg0;
        Date q = (Date) arg1;

        if (p.before(q))
        {
            return -1;
        }
        else if (p.after(q))
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }

    public boolean equals(Object o)
    {
        if (o instanceof CurrencyDateComparator)
        {
            CurrencyDateComparator c = (CurrencyDateComparator) o;

            return this.equals(o);
        }
        else
        {
            return false;
        }
    }
4

5 回答 5

3

您所有的日期都有不同的毫秒值,这些值不会打印在您的跟踪中。将毫秒设置为 0。

于 2013-01-23T18:35:18.643 回答
1

第一的

java.util.Date带有时间信息,您需要将时间信息归零,然后设置您想要设置的内容或从您的自定义比较中排除时间部分Comparator

第二

你的习惯Comparator是错误的和多余的。java.util.Date已经实现Comparable,因此您无需再次比较日期,只需.compare()在第一个Date实例上调用第二个实例作为参数。

第三

还要记住,MONTHS在 Caledar 中是零。一月 ==0不是1

第四

永远不要依赖默认值toString()on java.util.Date,始终使用SimpleDateFormatter将整个时间戳显示到毫秒的实例,包括TimeZone( yyyy-MM-dd'T'HH:mm:ssZ),最好是 ISO-8601 和UTCTimeZone 以确定性行为。

于 2013-01-23T18:35:56.877 回答
0

当您使用Calendar.getInstance()它时,它将“现在”返回到毫秒精度。更改 YMD 字段并不会清除其中的任何内容,因此您的两个日期可能相差一毫秒或二十,这不包含在toString()您看到输出的默认实现中。

如果要将日历设置为特定时间,最简单的方法是clear()在开始设置字段之前先进行设置。

于 2013-01-23T18:38:08.327 回答
0

当您调用 时Calendar.getInstance(),您会Calendar使用当前时间初始化。这包括小时、分钟、秒和毫秒。调用clearTime()它来将它们归零。

于 2013-01-23T18:39:06.660 回答
0

您可以改用此集合

Set<Date> dates = new TreeSet<Date>(CurrencyDateComparator.INSTANCE);
dates.add(date2);
dates.add(date1);
dates.add(date3);

enum CurrencyDateComparator implements Comparator<Date> {
    INSTANCE;

    static final long MILLI_PER_DAY = 86400000L;
    public int compare(Date d1, Date d2) {
        // older versions of Java can use Double.compare()
        return Long.compare(d1.getTime() / MILLIS_PER_DAY, d2.getTime() / MILLIS_PER_DAY);
    }
}
于 2013-01-23T18:43:33.003 回答