无法在Java / android中的现有比较器中添加对日期进行排序的逻辑

时间:2018-10-04 03:02:30

标签: java android sorting date comparator

我想添加一个条件,该条件也根据item.startReading的DATE(降序)进行排序。 item.startReading值具有字符串格式2018-10-20T12:05:41的日期值。但是我不知道如何 将此逻辑添加到当前代码中。在用户单击杂志或书本之前,item.startReading的值为null。 。当用户单击其中任何一个项目时,我希望最新的item.startReading会像下面一样转到顶部。 抱歉,我的解释很抱歉,但是自从我开始学习java / android以来,我真的需要知道该怎么做。一些例子或技巧会很可爱。 我希望收到您的来信。

  1. 杂志(2018-10-21T13:06:41)最新的日期项转到顶部
  2. 杂志(2018-10-20T12:05:41)

目前,我有以下比较器代码,其排序如下。

(在使用比较器之前)

  1. 杂志
  2. 杂志

(使用比较器后) 使用类型,最后使用ID的商品 ↓

  1. 杂志
  2. 杂志

我的比较器代码:

public Comparator<MyItem> myComparator = (item1, item2) -> {
    //How to add the desc date order with Dates?

    if (item1.typeInt == MyItemModel.TYPE_BOOK && item2.typeInt !=  MyItemModel.TYPE_BOOK) {
        return -1;
    } else if (item1.type !=  MyItemModel.TYPE_BOOK && item2.type ==  MyItemModel.TYPE_BOOK) {
        return 1;
    } else if (item1.type == MyItemModel.TYPE_MAGAZINE && item2.type != MyItemModel.TYPE_MAGAZINE) {
        return -1;
    } else if (item1.type != MyItemModel.TYPE_MAGAZINE && item2.type == MyItemModel.TYPE_MAGAZINE) {
        return 1;
    } 
    return (Integer.compare((int) item1.id, (int) item2.id)) * -1;
};

2 个答案:

答案 0 :(得分:1)

首先创建一个解析给定日期的函数

public Date parseDateFromString(String date){
    if(date == null) {
        return null;
    }
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-yy'T'HH:mm:ss", Locale.US);
    try {
        return simpleDateFormat.parse(date);
    } catch (ParseException e) {
        e.printStackTrace();
        return null;
    }
}

然后将其与Comparator之类的进行比较

if (item1.typeInt != item2.typeInt) {
    return item1.typeInt == MyItemModel.TYPE_MAGAZINE ? 1 : -1;
} else {
    if (parseDateFromString(item1.getStartReading()) == null) {
        return 0;
    } else if (parseDateFromString(item2.getStartReading()) == null) {
        return -1;
    } else {
        return parseDateFromString(item2.getStartReading()).after(parseDateFromString(item1.getStartReading())) ? 1 : -1;
    }
}

答案 1 :(得分:1)

public static Comparator<MyItem> myComparator
        // books first; sort by a Boolean expression that is false for books to put them first
        = Comparator.comparing((MyItem it) -> it.type != MyItemModel.TYPE_BOOK)
                // then magazines first
                .thenComparing(it -> it.type != MyItemModel.TYPE_MAGAZINE)
                // then by start date-time, nulls last, otherwise newest first
                .thenComparing(it -> it.startReading,
                        Comparator.nullsLast(Comparator.comparing((String start)
                                -> LocalDateTime.parse(start)).reversed()))
                // then by ID
                .thenComparing(it -> it.id);

由于您的API级别足以满足lambda的需求,因此我假设您也可以使用Comparator.comparingthenComparing等。这不仅麻烦,而且不易出错。我怀疑您打算在代码中使用type而不是typeInt,至少它是不一致的,这是您根本无法通过comparing来实现的。

Comparator.nullsLast最后对null个值进行排序(如果需要,可以使用姐妹方法nullsFirst)。您的字符串2018-10-21T13:06:41采用ISO 8601格式,LocalDateTime解析为其默认格式,即没有任何显式格式化程序。我们当然应该利用这一事实。 reversed颠倒了比较器的顺序,因此最新而不是最旧的项目排在第一位。

编辑:受this answer的启发,我正在对布尔值进行排序,以便首先获取书籍,然后再获取杂志。在布尔值的自然顺序中,false在true之前。我对it.type != MyItemModel.TYPE_BOOK进行排序,这对于书籍来说是错误的,也就是说,它们是第一位的,对其他所有书籍都是正确的。接下来,我也会为杂志做类似的事情。

进一步的改进

  • 声明属性的吸气剂,并使用MyItem::getId而不是it -> it.id
  • startReading存储为LocalDateTime,而不是存储在MyItem中的字符串,因此您无需为每次比较都进行解析(这有很多其他原因,这是一个很好的选择理念)。需要将其呈现给用户时,只需将其格式化为String