简体   繁体   English

集合为什么不从排序列表中删除重复项?

[英]Why doesn't the set remove duplicates from the sorted list?

Why doesn't the set remove duplicates from the sorted list ? 为什么集合不能从已排序列表中删除重复项? I have sorted the dates in ascending order which the first printed line shows but the set isn't removing the duplicates. 我已经按照日期的升序对日期进行了排序,第一条打印行显示了该日期,但是该日期并没有删除重复项。 Why is that ? 这是为什么 ? The program prints: 程序打印:
[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, Mon Apr 20 12:27:47 CDT 2009, Mon Apr 20 12:27:47 CDT 2009] [2009年4月20日星期一,CDT 2009年4月20日星期一,CDT 2009年4月20日,加拿大夏令时间2009年12月20日,星期日12:27:47] [2009年12月20日12月20日,星期日12:27:47 CST,星期一:CDT 2009:27:47,2009年4月20日星期一CDT:27:47]

Shouldn't creating a set remove the duplicate date from the collection ? 创建集不应该从集合中删除重复的日期吗?

    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;
        }
    }

All your dates have different millisecond values, that are not printed in your traces. 您所有的日期都有不同的毫秒值,这些值不会打印在迹线中。 Set the milliseconds to 0. 将毫秒设置为0。

First 第一

java.util.Date carries time information with it, you need to zero out the time information then set what you want to be set or exclude the time portion from the comparison inside your custom Comparator . java.util.Date带有时间信息, 您需要将时间信息清零,然后设置要设置的内容,或者从自定义Comparator内部的比较中排除时间部分。

Second 第二

Your custom Comparator is buggy and redundant. 您的自定义Comparator存在错误和冗余。 java.util.Date already implements Comparable so you don't need to compare dates again, just called .compare() on the first Date instance with the second one as an argument. java.util.Date已经实现Comparable因此您无需再次比较日期,只需在第一个Date实例上调用.compare() ,然后将第二个实例作为参数即可。

Third 第三

Also remember that MONTHS are ZERO based in Caledar. 还请记住, MONTHS是基于Caledar的零。 January == 0 not 1 . 一月== 0而不是1

Fourth 第四

Never rely on the default toString() on java.util.Date , always use a SimpleDateFormatter instance that displays the entire time stamp down to the milliseconds including a TimeZone ( yyyy-MM-dd'T'HH:mm:ssZ ), preferably ISO-8601 and UTC TimeZone for deterministic behavior. 永远不要依赖java.util.Date上的默认toString() ,始终使用SimpleDateFormatter实例,该实例显示整个时间戳(以毫秒为单位),包括TimeZoneyyyy-MM-dd'T'HH:mm:ssZ ),最好ISO-8601和UTC TimeZone用于确定性行为。

When you use Calendar.getInstance() it returns "now" to millisecond precision. 当您使用Calendar.getInstance()它将“毫秒”返回“毫秒”。 Changing the YMD fields does not clear any of that out, so your two dates are likely off by a millisecond or twenty, which is not included in the default toString() implementation that you're seeing output from. 更改YMD字段不会清除所有这些内容,因此您的两个日期可能相差一毫秒或二十毫秒,这不包括在您从中看到输出的默认toString()实现中。

If you want to set a calendar to a specific time, it is simplest to clear() it first before starting to set fields. 如果要将日历设置为特定时间,最简单的方法是在开始设置字段之前先将clear()

When you call Calendar.getInstance() , you get a Calendar initialized with the current time. 调用Calendar.getInstance() ,将获得一个使用当前时间初始化的Calendar This includes hours, minutes, seconds, and milliseconds. 这包括小时,分钟,秒和毫秒。 Call clearTime() on it to zero them out. 对其调用clearTime()将它们归零。

You can use this collection instead 您可以改用此收藏集

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM