简体   繁体   English

自定义比较器不排序时间

[英]Custom Comparator not sorting time

I am working on a project where I am comparing the date and time in a custom Comparator.我正在做一个项目,我在自定义比较器中比较日期和时间。 I actually concatenated the date with date and time.我实际上将日期与日期和时间连接起来。 When I debugged the issue, I realized that time is not getting sorted.当我调试问题时,我意识到时间没有得到排序。 Here is the snippet of my code from my Comparator.这是我的比较器中的代码片段。

Date dateObject1= new Date();
Date dateObject2  = new Date();

try {
    dateObject1 = sdf.parse(date1  + "T" + time1);
    dateObject2 = sdf.parse(date2  + "T" + time2);
} catch (Exception e) { }

if (dateObject1.compareTo(dateObject2) > 0)
    return 1;
else if (dateObject1.compareTo(dateObject2) < 0)
    return -1;
else
    return 0; 

Test cases: 1. date1 - 2019-12-13 , date2 - 2019-12-13 time1 - 08:00:00, time2 - 12:00:00测试用例: 1. date1 - 2019-12-13 , date2 - 2019-12-13 time1 - 08:00:00, time2 - 12:00:00

When i debugged the issue I found it's returning 0 for the above test case.当我调试问题时,我发现上面的测试用例返回 0。 I am not sure why it's happening but I intent to return -1 such that it's sorted in ascending order.我不确定为什么会发生这种情况,但我打算返回 -1,以便按升序排序。 Please advice.请指教。

Your problem is here你的问题在这里

} catch (Exception e) { }

You initialize your 2 dates, both of which get initialized to the current time ( System.currentTimeMillis() ).您初始化 2 个日期,这两个日期都被初始化为当前时间( System.currentTimeMillis() )。

Date dateObject1= new Date();
Date dateObject2  = new Date();

Your parsing then fails, but you swallow the exception so you never noticed it.您的解析随后失败,但您吞下了异常,因此您从未注意到它。

Then you try to sort two dates which are either exactly same, or separated by a couple of milliseconds, but are certainly unrelated to the actual timestamps that you're trying to sort.然后您尝试对两个完全相同或相隔几毫秒的日期进行排序,但肯定与您尝试排序的实际时间戳无关。

Check the exception, fix the parsing, and then it will work.检查异常,修复解析,然后它就会工作。

java.time and Comparator.comparing … thenComparing java.time 和 Comparator.comparing ... thenComparing

I don't know what your Java version is.我不知道你的 Java 版本是什么。 The following snippet works on Java 8 and above.以下代码段适用于 Java 8 及更高版本。 The most important ideas can be applied on Java 6 and 7 too.最重要的思想也可以应用于 Java 6 和 7。

    List<MyObject> listToBeSorted = Arrays.asList(
            new MyObject("2019-12-12", "11:53:50"),
            new MyObject("2019-12-11", "13:07:05"),
            new MyObject("2019-12-13", "05:02:16"),
            new MyObject("2019-12-11", "09:54:57"),
            new MyObject("2019-12-12", "05:53:52"),
            new MyObject("2019-12-13", "06:56:08"),
            new MyObject("2019-12-12", "02:31:55"),
            new MyObject("2019-12-11", "09:28:16"),
            new MyObject("2019-12-11", "20:58:55"));

    Comparator<MyObject> cmpr = Comparator.comparing(MyObject::getDate)
            .thenComparing(MyObject::getTime);

    listToBeSorted.sort(cmpr);

    listToBeSorted.forEach(System.out::println);

Output is:输出是:

 MyObject [date=2019-12-11, time=09:28:16] MyObject [date=2019-12-11, time=09:54:57] MyObject [date=2019-12-11, time=13:07:05] MyObject [date=2019-12-11, time=20:58:55] MyObject [date=2019-12-12, time=02:31:55] MyObject [date=2019-12-12, time=05:53:52] MyObject [date=2019-12-12, time=11:53:50] MyObject [date=2019-12-13, time=05:02:16] MyObject [date=2019-12-13, time=06:56:08]

You will observe that the objects have been sorted by date and objects with the same date also by time.您将观察到对象已按日期排序,并且具有相同日期的对象也按时间排序。 Here is the MyObject class that I used:这是我使用的MyObject类:

public class MyObject {

    LocalDate date;
    LocalTime time;

    public MyObject(String dateString, String timeString) {
        date = LocalDate.parse(dateString);
        time = LocalTime.parse(timeString);
    }

    public LocalDate getDate() {
        return date;
    }

    public LocalTime getTime() {
        return time;
    }

    @Override
    public String toString() {
        return "MyObject [date=" + date + ", time=" + time + "]";
    }

}

The two key messages are:两个关键信息是:

  1. Don't keep your dates and times as strings in your objects.不要将日期和时间作为字符串保存在对象中。 Keep proper date and time objects.保留正确的日期和时间对象。 It may require parsing strings when you build your objects, but everything else gets noticeably easier.构建对象时可能需要解析字符串,但其他一切都会变得明显容易。
  2. Don't use Date and SimpleDateFormat at all.根本不要使用DateSimpleDateFormat Use classes from java.time, the modern Java date and time API.使用 java.time 中的类,现代 Java 日期和时间 API。 In this case LocalDate and LocalTime .在这种情况下LocalDateLocalTime The SimpleDateFormat and Date classes are poorly designed and long outdated, the former in particular notoriously troublesome. SimpleDateFormatDate类的设计很差,而且已经过时了,前者尤其麻烦。 The modern API is so much nicer to work with.现代 API 使用起来要好得多。

The advantage of the Comparator methods comparing and thenComparing is not so much that code gets considerably shorter. Comparator方法comparingthenComparing的优点并不是代码变得相当短。 The really important gain is that writing comparators in this style is much less error prone, and the code reads more naturally.真正重要的好处是,以这种风格编写比较器更不容易出错,并且代码读取更自然。

What went wrong in your code?你的代码出了什么问题?

The problem is in the line that you posted in a comment:问题出在您在评论中发布的行中:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 

This formatter only parses the date from each string and ignores the time.此格式化程序仅解析每个字符串中的日期并忽略时间。 It's one of many confusing traits of SimpleDateFormat that it is happy to parse only a part of the string and doesn't draw our attention to the fact that some of the text is ignored — in this case the T and the entire time. SimpleDateFormat的许多令人困惑的特征之一是它很高兴只解析字符串的一部分,并且不会让我们注意到某些文本被忽略的事实——在这种情况下是T和整个时间。

Link关联

Oracle tutorial: Date Time explaining how to use java.time. Oracle 教程:解释如何使用 java.time 的日期时间

Just return the value of the comparison since that is what you return anyway.只需返回比较的值,因为无论如何您都会返回该值。

Date dateObject1= new Date();
Date dateObject2  = new Date();
try {
       dateObject1 = sdf.parse(date1  + "T" + time1);
       dateObject2 = sdf.parse(date2  + "T" + time2);
} catch (Exception e) {
     e.printStackTrace();  // always print these.  They are there to help you.
}
return dateObject1.compareTo(dateObject2);

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

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