无法在 Java/android 的现有比较器中添加按日期排序的逻辑
Unable to add a logic to sort with dates in the existing comparator in Java/android
我想添加一个条件,该条件也根据 item.startReading 的日期(降序顺序)进行排序。
item.startReading
值具有字符串格式 2018-10-20T12:05:41
中的日期值。但我不知道该怎么做
将此逻辑添加到当前代码中。在用户单击杂志或图书项目之前,item.startReading
的值为 null
。
.当用户单击其中一项时,我希望最新的 item.startReading
像下面这样转到顶部。
抱歉我的解释,但自从我开始学习 java/android 以来,我真的需要知道该怎么做。一些例子或提示会很可爱。
我很想听听你的意见。
- 杂志 (2018-10-21T13:06:41) 最新日期项目到顶部
- 杂志 (2018-10-20T12:05:41)
- 书籍
- 书籍
目前,我有以下比较器代码,可以进行如下排序。
(使用比较器之前)
- 杂志
- 书籍
- 杂志
- 书籍
(使用比较器后)
使用类型重新订购,最后使用 ID
↓
- 书籍
- 书籍
- 杂志
- 杂志
我的比较代码:
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;
};
首先创建一个解析给定日期的函数
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;
}
}
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.comparing
和 thenComparing
等。这样做。它不仅更简洁,而且更不容易出错。我怀疑您打算在代码中使用 type
而不是 typeInt
,至少它不一致,您根本无法使用 comparing
.
来实现不一致
Comparator.nullsLast
最后对 null
值进行排序(如果您需要,可以使用姊妹方法 nullsFirst
)。您的 2018-10-21T13:06:41
字符串采用 ISO 8601 格式,LocalDateTime
解析为默认格式,即没有任何显式格式化程序。我们当然应该利用这个事实。 reversed
颠倒比较器的顺序,因此最新的而不是最旧的项目排在第一位。
编辑:在 的启发下,我正在对布尔值进行排序以先获取书籍,然后再获取杂志。在布尔值的自然排序中,false 在 true 之前出现。我按 it.type != MyItemModel.TYPE_BOOK
排序,这对书籍来说是错误的,也就是说,它们排在第一位,对其他所有内容都是正确的。接下来我为杂志做类似的事情。
进一步可能的改进
- 为您的属性声明 getter 并使用
MyItem::getId
而不是 it -> it.id
。
- 将
startReading
存储为 LocalDateTime
而不是 MyItem
中的字符串,因此您无需为每次比较都进行解析(还有许多其他原因一个好主意)。当您需要将其呈现给用户时,只需将其格式化为 String
。
我想添加一个条件,该条件也根据 item.startReading 的日期(降序顺序)进行排序。
item.startReading
值具有字符串格式 2018-10-20T12:05:41
中的日期值。但我不知道该怎么做
将此逻辑添加到当前代码中。在用户单击杂志或图书项目之前,item.startReading
的值为 null
。
.当用户单击其中一项时,我希望最新的 item.startReading
像下面这样转到顶部。
抱歉我的解释,但自从我开始学习 java/android 以来,我真的需要知道该怎么做。一些例子或提示会很可爱。
我很想听听你的意见。
- 杂志 (2018-10-21T13:06:41) 最新日期项目到顶部
- 杂志 (2018-10-20T12:05:41)
- 书籍
- 书籍
目前,我有以下比较器代码,可以进行如下排序。
(使用比较器之前)
- 杂志
- 书籍
- 杂志
- 书籍
(使用比较器后) 使用类型重新订购,最后使用 ID ↓
- 书籍
- 书籍
- 杂志
- 杂志
我的比较代码:
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;
};
首先创建一个解析给定日期的函数
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;
}
}
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.comparing
和 thenComparing
等。这样做。它不仅更简洁,而且更不容易出错。我怀疑您打算在代码中使用 type
而不是 typeInt
,至少它不一致,您根本无法使用 comparing
.
Comparator.nullsLast
最后对 null
值进行排序(如果您需要,可以使用姊妹方法 nullsFirst
)。您的 2018-10-21T13:06:41
字符串采用 ISO 8601 格式,LocalDateTime
解析为默认格式,即没有任何显式格式化程序。我们当然应该利用这个事实。 reversed
颠倒比较器的顺序,因此最新的而不是最旧的项目排在第一位。
编辑:在 it.type != MyItemModel.TYPE_BOOK
排序,这对书籍来说是错误的,也就是说,它们排在第一位,对其他所有内容都是正确的。接下来我为杂志做类似的事情。
进一步可能的改进
- 为您的属性声明 getter 并使用
MyItem::getId
而不是it -> it.id
。 - 将
startReading
存储为LocalDateTime
而不是MyItem
中的字符串,因此您无需为每次比较都进行解析(还有许多其他原因一个好主意)。当您需要将其呈现给用户时,只需将其格式化为String
。