【问题标题】:How to sort a list of objects by date when date is String? [duplicate]当日期为字符串时,如何按日期对对象列表进行排序? [复制]
【发布时间】:2018-04-27 05:15:42
【问题描述】:

我有以下 Java POJO,Start date 是一个字符串:

POJO 对象:

public class Schedule {

    private String id;

    private String startDate = "";

    //const and getters and setters
}

我想按开始日期字段对这些对象的列表进行排序:

将 POJOS 添加到列表中:

List<Schedule> schedules = new ArrayList<Schedule>();

Schedule s1 = new Schedule();
s1.setStartDate("2018-09-01T15:00:00+0000");

Schedule s2 = new Schedule();
s2.setStartDate("2018-09-15T15:00:00+0000");

schedules.add(s1);
schedules.add(s2);

我试过写一个comparator,但它似乎不起作用,有没有办法按日期(最早在先)对strings 进行排序?

编辑:我目前使用的是 Java 7

【问题讨论】:

  • 这些时间戳有一个时区部分。我认为您需要将字符串转换为某种日期,然后进行排序。
  • 为什么不把startDate 字段的类型改为OffsetDateTime?我应该说这是更好更健全的建模。
  • 如果——但仅当——区域偏移量总是+0000,你可以对字符串进行排序。不过,不推荐使用肮脏的解决方案。
  • 我的两分钱:a。如果您总是需要排序格式的数据并且数据将是唯一的。你应该选择 SortedSet 而不是 ArrayList。为此,您需要在 Schedule 类中实现 Comparable 接口。使用以下模式解析日期 DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ", Locale.ENGLISH);
  • @akshayapandey, SortedSet 可能是一个好主意,具体取决于要求和设计。无论如何,请避免使用早已过时的SimpleDateFormat 班级和朋友。现代和更好的等价物是DateTimeFormatter

标签: java string list date arraylist


【解决方案1】:

我认为您可以创建一个类似于以下结构的自定义比较器:

Collections.sort(datestring, new Comparator<String>() {
    DateFormat df = new SimpleDateFormat("your format");
    @Override
    public int compare(String s1, String s2) {
       try {
            return df.parse(s1).compareTo(df.parse(s2));
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }
});

【讨论】:

  • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。今天我们已经好多了。在这种情况下,现代 OffsetDateTime 甚至可以直接解析字符串,而无需任何显式格式化程序或格式化模式字符串。
  • 是的,但它是 Java 8,对于他的问题,我认为他没有使用 Java 8...
  • Java 8 早已广泛使用。如果 OP 使用的是 Java 7(或 6),我仍然建议获取 the ThreeTen Backport,这是现代日期和时间 API 到 Java 6 和 7 的反向移植,并使用 OffsetDateTime
  • @canillas 请展示我如何使用它返回新的排序列表?是的,你是对的,我使用的是 java 7
  • 您必须创建比较器并对其进行调整。我的代码仅用于字符串列表,您需要为您的自定义对象创建它(但更改它需要 1 或 2 分钟......只需更改 Shedule 的字符串并解析 shedule.getStartDate)。然后你可以调用 collection.sort(mySheduleList, new myCustomComparator())
【解决方案2】:

基本上,您需要将时区转换为日期作为排序操作的一部分:

schedules.sort((s1, s2) -> {
  ZonedDateTime d1 = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(s1.getStartDate(), ZonedDateTime::from);
  ZonedDateTime d2 = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(s2.getStartDate(), ZonedDateTime::from);

  return d1.compareTo(d2);
});

【讨论】:

    【解决方案3】:

    最好的方法是将您的字符串转换为 Schedule 类中的日期。

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    
    public class Schedule {
    
        private String id;
    
        private String startDate = "";
    
        private Date startDateAsDate;
    
        public Date getStartDateAsDate() {
            if (startDateAsDate != null) {
                return startDateAsDate;
            }
            try {
                startDateAsDate = (Date) SDF.parseObject(startDate);
                return startDateAsDate;
            } catch (Exception e) {
                return null;
            }
        }
    }
    
    private class ScheduleComparator implements Comparator<Schedule> {
    
        @Override
        public int compare(Schedule o1, Schedule o2) {
            // TODO Auto-generated method stub
            return o1.getStartDateAsDate().compareTo(o2.getStartDateAsDate());
        }
    
    }
    
    Collections.sort(scheduleList, new ScheduleComparator());
    // or
    Arrays.sort(scheduleArray, new ScheduleComparator());
    

    【讨论】:

    • 是否建议使用 java.util.Date 类?
    • 当您使用 Java 8 或更高版本时,最好使用 java.time 中的等效项。我用过java.util.Date,因为我不知道你用的是哪个java版本。
    • @Yash,感谢您的提问,2017 年我应该说不。最好使用现代 Java 数据和时间 API,特别是 OffsetDateTime(在其他一些答案中使用的 ZonedDateTime 也可以)。
    • 啊,@Yash,我忘了,Java 8 中有一个错误,所以它不会解析没有冒号的偏移量 (+00:00)。它适用于 Java 9! Java 8 解决方法,要么使用显式格式化程序,要么自己插入冒号。
    • @OleV.V.确切地!在 Java 9 中它正在工作!非常感谢:)
    【解决方案4】:

    可以试试 java 8 Comparator 吗?

    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
    schedules.sort(Comparator.comparing(s -> dateTimeFormatter.parse(s.getStartDate(), ZonedDateTime::from)));
    

    Java 8 ZonedDateTime 在偏移量中需要一个冒号,+00:00。代码应该在 Java 9 中工作!

    Java 8 解决方法,要么使用显式格式化程序,要么自己插入冒号。 – Ole V.V.

    List<Schedule> schedules = new ArrayList<>();
    
    Schedule s1 = new Schedule();
    s1.setStartDate("2018-09-01T15:00:00+00:00"); //add a colon in the offset
    
    Schedule s2 = new Schedule();
    s2.setStartDate("2018-09-15T15:00:00+00:00"); //add a colon in the offset
    
    schedules.add(s1);
    schedules.add(s2);
    
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
    schedules.sort(Comparator.comparing(s -> dateTimeFormatter.parse(s.getStartDate(), ZonedDateTime::from)));
    

    或者您需要自己创建一个格式化程序并在上面的 lambda 中使用它。

    //final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("your format");
    

    【讨论】:

    • 这将如何处理日期字符串中的区域组件?
    • 在 Java 8 中,此代码将不起作用。 java.time.format.DateTimeParseException: Text '2018-09-15T15:00:00+0000' could not be parsed at index 19 以 OP 为例。
    • Java 8 ZonedDateTime 需要在偏移量中使用冒号 +00:00。 @LazerBanana,您的代码应该可以在 Java 9 中运行! Java 8 解决方法,要么使用显式格式化程序,要么自己插入冒号。
    • 它确实在我的本地运行 java 9,抱歉误导。我会编辑答案。
    • 不幸的是我正在使用 Java 7
    猜你喜欢
    • 2018-07-07
    • 2020-11-11
    • 2013-01-06
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    相关资源
    最近更新 更多