【问题标题】:Sort by date descending comparator not working as expected按日期降序比较器未按预期工作
【发布时间】:2013-01-02 16:12:16
【问题描述】:

试图理解以下输出:

public class CommunicationComparator implements Comparator<Communication> {
    @Override
    public int compare(Communication comm1, Communication comm2) {
        long t1 = comm1.getDate().getTime();
        long t2 = comm2.getDate().getTime();
        return (int) (t2 - t1);
    }
}

getDate() 方法返回一个 java.sql.Timestamp。

这是排序前的输出:

for (Communication n : retVal) {
    System.out.println(n.getDate().toString());
}

2012-10-03 10:02:02.0
2012-10-07 03:02:01.0
2012-10-08 13:02:02.0
2012-10-09 03:02:00.0
2012-11-26 10:02:05.0
2012-11-28 11:28:11.0
2012-12-03 12:03:01.0
2012-12-06 15:03:01.0
2012-12-13 14:03:00.0
2012-12-28 11:03:00.0
2012-12-28 13:49:21.0

之后:

Collections.sort(retVal, new CommunicationsComparator());

2012-12-13 14:03:00.0
2012-12-06 15:03:01.0
2012-12-03 12:03:01.0
2012-11-28 11:28:11.0
2012-10-09 03:02:00.0
2012-10-08 13:02:02.0
2012-11-26 10:02:05.0
2012-10-07 03:02:01.0
2012-10-03 10:02:02.0
2012-12-28 13:49:21.0
2012-12-28 11:03:00.0

任何想法为什么底部的两个对象可能无法正确排序?我正在使用这个时间戳的 MySQL JDBC 实现。

【问题讨论】:

  • 为什么要对时间戳减法进行排序?更具体地说,实现这一点的规范是什么?
  • java.sql.Timestamp 实现了Comparable,因此有一个compareTo() 方法。为什么不像 return comm1.getDate().compareTo(comm2.getDate()); 那样直接委托给它呢?
  • @BalusC 这是最好的方法,老实说,我不去想它就觉得很愚蠢。这就是我要做的。
  • 不客气。看来彼得后来复制了这个答案,所以我不会转发它。

标签: java sorting comparator


【解决方案1】:

最后 2 个日期与更早日期之间的差值将溢出整数。

也许更好的解决方案是比较这些值,而不是减去它们。

    long t1 = comm1.getDate().getTime();
    long t2 = comm2.getDate().getTime();
    if(t2 > t1)
            return 1;
    else if(t1 > t2)
            return -1;
    else
            return 0;

【讨论】:

  • 对我来说看起来完美且安全。
  • @MrSmith42 我犯了多么严重的初学者错误!感谢您向我指出这一点。 :)
  • 使用三元运算符的一种简便方法:return t1 == t2 ? 0 : t1 &lt; t2 ? -1 : 1;
  • 我不会说初学者的错误 - 但 op 的回复骑士非常好的洞察力。
【解决方案2】:

如果差值大于大约 25 天,则会发生溢出。 (一个 int 不能以毫秒为单位表示比大约 25 天更大的时间差)。这会使比较不正确。

这可以通过将return语句改为:

return Long.signum(t2 - t1);

【讨论】:

  • 你仍然有一个(对于这个用例来说是不切实际的,因为两个值都是正数)溢出的可能性。通常最好是比较而不是减去...
【解决方案3】:

你可以使用

return Long.compare(t2, t1);

但你最好比较日期。

return comm2.getDate().compareTo(comm1.getDate());

【讨论】:

    【解决方案4】:

    我的第一个想法是问题是溢出。 t1t2longs。不同的可能不适合 int。

    我会检查的。

    如果二级比较对你来说足够好,你应该尝试:

    return (int) ((t2 - t1)/1000);
    

    这并不能保证不会发生溢出。 我至少会添加一个测试。

    我认为最好的答案不是我的。 我最喜欢的是:

        if(t2 > t1)
            return 1;
        else if(t1 > t2)
            return -1;
        else
            return 0;
    

    【讨论】:

    • 问题是,区别是否也总是适合int。它是如此接缝。
    【解决方案5】:

    在 java 8 及更高版本中,我们可以通过以下方式以非常干净和简单的方式做到这一点:

    list.stream().max(Comparator.comparing(YourCustomPojo::yourDateField))
    

    这适用于任何具有支持compareTo() 的字段类型的Pojo。 java.sql.Timeastampjava.util.Date 提供对这种方法的开箱即用支持。

    查看java文档here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-04
      • 2019-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      相关资源
      最近更新 更多